How to run Elixir Supervisor in escript

I have a mixing project with as simple as Supervisor and GenServer. When I call from iex:

EchoCmd.Supervisor.start_link([:Hello]) GenServer.call(:echoserver, :echo) GenServer.call(:echoserver, :mumble) GenServer.call(:echoserver, :echo) 

Error: mumble throws an exception, then GenServer restarts, and second: the echo call works fine.

If I run the code in any other way, Supervisor will not be able to restart GenServer. For example, I create a project project with a main module as follows:

 defmodule EchoCmd.Echo do def main(args) do EchoCmd.Supervisor.start_link([:Hello]) GenServer.call(:echoserver, :echo) GenServer.call(:echoserver, :mumble) GenServer.call(:echoserver, :echo) end end 

Call: mumble throws an exception and escript exits without restarting the supervisor using GenServer.

I did not include Supervisor code and Server modules because they work fine when calling from iex, so I assume they are not needed here.

Do I have a conceptual misunderstanding? Is it not possible, or am I doing something wrong?

+6
source share
2 answers

The problem is not with your server and supervisor, but with the way you name them. If the server quits while another process is waiting for a response to GenServer.call , the calling process also crashes, so the last call will never happen. The reason for this is the inability to continue the process in an invalid state if the synchronous call fails ( GenServer.call is synchronous, not GenServer.cast ). If you do this just to check the supervisor, you can try:

 defmodule EchoCmd.Echo do def main(args) do EchoCmd.Supervisor.start_link([:Hello]) GenServer.cast(:echoserver, :echo) GenServer.cast(:echoserver, :mumble) GenServer.cast(:echoserver, :echo) end end 

The reason it works in iex is because iex traps the output and allows another line to be entered.

+5
source

The behavior of the script is correct. You just skipped how the iex shell "helps you."

What do you do in your code, start the process connected , and not reset it. And since it is a related process, when it goes down, it is intended to bring down all related processes. There may be some “exceptions,” but what happens to your escript process.

Both shell managers and prcess can handle the message "I'm dead, so you should." They do this by changing the processing method (a related process, not a dying one) processes such messages. It allows them to receive them as regular messages (which you could receive in receive if you want), rather than special, internal ones. To change this bahaviour, they use Process.flag( :trap_exit, :true) ( elixir doc , pointing to eralng one ). This allows the shell to simply print the death of killed processes, rather than dying every time you do something bad.

So you could do the same. Change this flag, and if you do not agree with the pattern in receive on such messages. But I do not think what you are looking for. Since your process is singleton, and the supervisor does all the restarts, you really have no reason to refer to it in the first place. There is no need for death updates and re-launches, just let the manager worry about it. This is exactly the same as Joe Armstrong said (maybe to rephrase)

You do not need to know how to fix a vending machine in order to use it.

So simple, start , not start_link .

However, you might consider creating a connection with a supervisor who might also die after too many restarts (he may have been ordered to behave this way). And that allows you to take it (and a controlled process) when you die. Or it may be associated with your manager, application manager, or in some other way. It depends on your domain, and there is no bad decision, you just need to check what works with you. This is a design decision, and you either need to experiment or learn more about it:

http://elixir-lang.org/getting_started/mix_otp/5.html

http://www.erlang.org/doc/design_principles/des_princ.html

http://learnyousomeerlang.com/supervisors

+3
source

Source: https://habr.com/ru/post/978264/


All Articles