otp


How to run Elixir Supervisor in escript


I have a mix project with as simple as possible a 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)
The :mumble call raises an exception, then the GenServer is restarted and the second :echo call works ok.
If I run the code in any other way the Supervisor fails to restart the GenServer. For example, I create an escript of the project with the 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
The :mumble call raises an exception and the escript terminates without the Supervisor restarting the GenServer.
I've not included the Supervisor and Server modules code because they work fine when called from iex, so I'm guessing they're not needed here.
Do I have a conceptual misunderstanding? Is this not possible, or am I doing something wrong?
The problem lies not in your server and supervisor, but in the way you're calling them. If the server exits while another process is waiting for a reply to GenServer.call, the calling process exits too, so the last call never happens. The reason for this is the process couldn't possibly continue in an invalid state if a synchronous call failed (GenServer.call is synchronous as opposed to GenServer.cast). If you're doing this just to test the supervisor, then 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 that iex traps the exit and allows you to type in another line.
Escript behaviour is correct. You just missing how iex shell "helps you".
What you are doing in your code is starting a linked process, and than crashing it. And since it is a linked process, when it goes down, it suppose to bring down all linked processes. There could be some "exceptions", but that what's happening to your escript process.
Both shell and prcess supervisor can handle such "I died, so should you" message. They do it by changing the way process (linked process, not the dying one) processes such messages. It allows them to receive they as normal messages (that you could receive in receive clause if you would like to) rather than special, internal ones. To change this bahaviour they use Process.flag( :trap_exit, :true) (elixir doc pointing to eralng's one). It allows shell to just print death of killed processes, rather that dying every time you do something bad.
So you could do same thing. Change this flag, and if you wan't pattern match in receive on such messages. But I don't think that's what you looking for. Since your process is singleton, and supervisor does all restarting, you don't really have any reason to link to it in first place. There is no need for updates on deaths and restarts, just let supervisor worry about that. It's just like Joe Armstrong said (might be paraphrasing)
You don't need to know how to fix vending machine to use it.
So just, start, rather than start_link.
That said, you might consider creating link with supervisor, which also might die after too many restarts (he might be told to behave in such way). And it allows you to take him (and supervised process) when you die. Or he could be linked to your supervisor, or application supervisor, or in some other manner. It depends on your domain, and there is no bad decision, you just have to check what's working for you. It is design decision, and you either have to experiment or read 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

Related Links

How to build a release archive with rebar3 together with lager
Open trip planner internal algorthim
What are the architectural differences between Erlang/OTP and OpenResty?
GTFS fares allocation depending on time
Using GTFS real time feed
How to run Elixir Supervisor in escript
Online Users Storing Elixir
How to create a distributed application on elixir?
What version of .NET does OTP.NET use? [closed]

Categories

HOME
service-worker
time-complexity
linkedin
character-encoding
3d
shiro
can
nuget
soa
rds
x264
android-json
elasticsearch-5
radgridview
selectize.js
event-sourcing
alpacajs
esoteric-languages
atlassian-stash
aws-sdk
red5
fat
datastax-enterprise-graph
user-defined-functions
google-earth
mobx
testbed
jbutton
fstream
android-maps-extensions
python-import
baidu-map
reason
imagenet
connection-pool
setup.py
stringtokenizer
softmax
photos
double-click
yii2-api
amq
ngmaterial
avx
jqchart
renaming
pocketsphinx-android
choice
cudd
envi
signalr.client
refinerycms
http-status-code-401
uiactionsheet
inf
linklabel
decimalformat
pypiserver
xvim
android-launcher
visual-sourcesafe-2005
haskell-warp
wso2greg
dnssec
teamcity-9.1
snackbar
jquery-forms-plugin
gamekit
procedural-programming
iiop
crowd
psr-4
human-computer-interface
codeplex
xml-dsig
file-not-found
hibernate-entitymanager
http-patch
ice-cube
modular
mvc-editor-templates
poker
actiondispatch
android-sdk-2.3
device-width
mkv
listitem
azman
relative
timthumb
photolibrary
qglwidget
non-clustered-index
aspmenu
pagemethods
django-piston
wspbuilder

Resources

Encrypt Message