Current section

Files

Jump to
singleton lib singleton.ex
Raw

lib/singleton.ex

defmodule Singleton do
@moduledoc """
Singleton application.
The top supervisor of the `:singleton` OTP application is a
DynamicSupervisor. Singleton can manage many singleton processes at
the same time. Each singleton is identified by its unique `name`
term.
"""
use Application
require Logger
def start(_, _) do
DynamicSupervisor.start_link(
strategy: :one_for_one,
name: Singleton.Supervisor
)
end
@doc """
Start a new singleton process.
This function needs to be executed on all nodes where the singleton
process is allowed to live. The actual process will be started only
once; a manager process is started on each node for each singleton
to ensure that the process continues on (possibly) another node in
case of node disconnects or crashes.
"""
def start_child(module, args, name) do
child_name = name(module, args)
spec =
{Singleton.Manager,
[mod: module, args: args, name: name, child_name: child_name]}
DynamicSupervisor.start_child(Singleton.Supervisor, spec)
end
def stop_child(module, args) do
child_name = name(module, args)
case Process.whereis(child_name) do
nil -> {:error, :not_found}
pid -> DynamicSupervisor.terminate_child(Singleton.Supervisor, pid)
end
end
defp name(module, args) do
bin = :crypto.hash(:sha, :erlang.term_to_binary({module, args}))
String.to_atom("singleton_" <> Base.encode64(bin, padding: false))
end
end