This project is used to show three methods of adding event handlers to a GenEvent manager.
- use
add_handler:
- this adds a handler to the
GenEventmanager, but does not do any supervision and is not fault tolerant
- use
add_mon_handlerwithout handling exits:
- this adds a monitored handler to the
GenEventmanager, but does not explicitly handle :gen_event_EXIT messages. instead it relies on crashing the server its in so that it can be restarted by its supervisor
- user
add_mon_handlerhandle exits:
- this adds a monitored handler to the
GenEventmanager, and explicitly handles exits. reading the event handler for any reason that is not:normalor:shutdown
In addition to the three handlers there are also two supervisors. One supervisor manages the three handlers with a :one_for_one strategy. The other manages the GenEvent manager and the handlers supervisor with a :one_for_all strategy. This ensures the handlers are re-added if the manager crashes for any reason.
defmoduleEventHandlerdouseGenEventrequireLoggerdefinit(parent)do{:ok,parent}enddefhandle_event({:log,msg},parent)do"handled log: #{inspectmsg} in #{__MODULE__}"|>Logger.info{:ok,parent}enddefhandle_event({:crash,_},parent)do"crash event handler #{__MODULE__}"|>Logger.info1=2enddefhandle_event(event,parent)do"handled event: #{inspectevent} in #{__MODULE__}"|>Logger.info{:ok,parent}endenddefmoduleEventHandlerServerdodefstart_link(opts)doGenServer.start_link(__MODULE__,opts,[]);enddefinit([opts])doGenEvent.add_handler(opts.manager_name,EventHandler,self()){:ok,opts}endenddefmoduleEventHandlerServerdodefstart_link(opts)doGenServer.start_link(__MODULE__,opts,[]);enddefinit([opts])do:ok=GenEvent.add_mon_handler(opts.manager_name,EventHandler,self()){:ok,opts}endenddefmoduleEventHandlerServerdodefstart_link(opts)doGenServer.start_link(__MODULE__,opts,[]);enddefinit([opts])dostart_handler(opts){:ok,opts}enddefstart_handler(opts)do:ok=GenEvent.add_mon_handler(opts.manager_name,EventHandler,self())enddefhandle_info({:gen_event_EXIT,handler,reason},state)whenreasonin[:normal,:shutdown]do{:stop,reason,state}enddefhandle_info({:gen_event_EXIT,handler,reason},state)dostart_handler(state){:noreply,state}endend