Skip to content

TattdCodeMonkey/gen_event_patterns

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
lib
 
 
 
 
 
 
 
 
 
 

Elixir GenEvent Testing

This project is used to show three methods of adding event handlers to a GenEvent manager.

  1. use add_handler:
  • this adds a handler to the GenEvent manager, but does not do any supervision and is not fault tolerant
  1. use add_mon_handler without handling exits:
  • this adds a monitored handler to the GenEvent manager, 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
  1. user add_mon_handler handle exits:
  • this adds a monitored handler to the GenEvent manager, and explicitly handles exits. reading the event handler for any reason that is not :normal or :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.

Generic Event Handler used in module

defmodule EventHandler do
  use GenEvent
  require Logger

  def init(parent) do
    {:ok, parent}
  end

  def handle_event({:log, msg}, parent) do
    "handled log: #{inspect msg} in #{__MODULE__}"
    |> Logger.info

    {:ok, parent}
  end

  def handle_event({:crash, _}, parent) do
    "crash event handler #{__MODULE__}"
    |> Logger.info

    1 = 2
  end

  def handle_event(event, parent) do
    "handled event: #{inspect event} in #{__MODULE__}"
    |> Logger.info

    {:ok, parent}
  end
end

Pattern 1 - basic event handler with no monitoring

defmodule EventHandlerServer do
  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts, []);
  end

  def init([opts]) do
    GenEvent.add_handler(opts.manager_name, EventHandler, self())

    {:ok, opts}
  end
end

Pattern 2 - monitored event handler

defmodule EventHandlerServer do
  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts,[]);
  end

  def init([opts]) do
    :ok = GenEvent.add_mon_handler(opts.manager_name, EventHandler, self())

    {:ok, opts}
  end
end

Pattern 3 - monitored event handler, restarts handler on exit

defmodule EventHandlerServer do
  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts,[]);
  end

  def init([opts]) do
    start_handler(opts)
    {:ok, opts}
  end

  def start_handler(opts) do
    :ok = GenEvent.add_mon_handler(opts.manager_name, EventHandler, self())
  end

  def handle_info({:gen_event_EXIT, handler, reason}, state)
    when reason in [:normal, :shutdown] do
    {:stop, reason, state}
  end

  def handle_info({:gen_event_EXIT, handler, reason}, state) do
    start_handler(state)

    {:noreply, state}
  end
end

About

exploration with elixir GenEvent handlers

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages