process_tree_dictionary v1.0.1 ProcessTreeDictionary
Implements a dictionary that is scoped to a process tree by replacing the group leader with a process that:
- Maintains a dictionary of state
- Forwards all unrecognized messages to the original group leader so that IO still works
Any process can be the root of its own process tree by starting a
ProcessTreeDictionary
.
The Erlang docs provide a summary of what a group leader is:
Every process is a member of some process group and all groups have a group leader. All I/O from the group is channeled to the group leader. When a new process is spawned, it gets the same group leader as the spawning process.
Since every new process inherits the group leader from its parent, a process
can start a ProcessTreeDictionary
in place of its existing group leader, and
every descendant process will inherit it, allowing them to access the state
of the same ProcessTreeDictionary
.
Note that all functions provided by this module rely upon side effects. Since referential transparency is a primary value of Elixir, Erlang, and functional programming in general, and none of the functions provided by this module are referentially transparent, we recommend you limit your usage of this module to specialized situations, such as for building test fakes to stand-in for stateful modules.
Important caveat: if any processes in your tree start an application with
Application.start
, Application.ensure_started
, or
Application.ensure_all_started
, the started application processes will not
be a part of the process tree, because OTP manages application starts for you.
If you need to access the ProcessTreeDictionary
from the started processes,
you’ll need to start the supervisor of the application yourself. For more info,
see the Erlang docs.
Summary
Functions
Starts a ProcessTreeDictionary
if this process does not already have access
to one
Gets the value for the given key
from the dictionary
Puts the given value
into the dictionary under the given key
Updates the key
in the dictionary using the given function
Types
key :: simple_key | [simple_key]
simple_key :: String.t | atom | integer
Functions
Specs
ensure_started :: :ok
Starts a ProcessTreeDictionary
if this process does not already have access
to one.
If a ProcessTreeDictionary
has already been started in this process or in a
parent process (prior to this process being spawned), this will be a no-op.
Examples
iex> ProcessTreeDictionary.ensure_started()
:ok
Specs
get(key :: key, default :: any) :: any
Gets the value for the given key
from the dictionary.
Returns the default
value if the ProcessTreeDictionary
has not been started
or if the dictionary does not contain key
. The key
can be a simple key
(such as a string, atom, or integer) or a key path, expressed as a list.
Examples
iex> ProcessTreeDictionary.ensure_started()
iex> ProcessTreeDictionary.put(:language, "Elixir")
iex> ProcessTreeDictionary.get(:language)
"Elixir"
iex> ProcessTreeDictionary.ensure_started()
iex> ProcessTreeDictionary.put([MyApp, :meta, :language], "Elixir")
iex> ProcessTreeDictionary.get([MyApp, :meta, :language])
"Elixir"
Specs
put(key :: key, value :: any) :: :ok
Puts the given value
into the dictionary under the given key
.
The key
can be a simple key (such as a string, atom, or integer)
or a key path, expressed as a list.
Raises an error if a ProcessTreeDictionary
has not been started.
Examples
iex> ProcessTreeDictionary.ensure_started()
iex> ProcessTreeDictionary.put(:language, "Elixir")
:ok
iex> ProcessTreeDictionary.ensure_started()
iex> ProcessTreeDictionary.put([MyApp, :meta, :language], "Elixir")
:ok
Specs
update!(key :: key, (any -> any)) :: any
Updates the key
in the dictionary using the given function.
The key
can be a simple key (such as a string, atom, or integer) or a key
path, expressed as a list.
If the key does not exist, raises a KeyError
.
Examples
iex> ProcessTreeDictionary.ensure_started()
iex> ProcessTreeDictionary.put(:language, "Elixir")
iex> ProcessTreeDictionary.update!(:language, &String.downcase/1)
iex> ProcessTreeDictionary.get(:language)
"elixir"
iex> ProcessTreeDictionary.ensure_started()
iex> ProcessTreeDictionary.put([MyApp, :meta, :language], "Elixir")
iex> ProcessTreeDictionary.update!([MyApp, :meta, :language], &String.downcase/1)
iex> ProcessTreeDictionary.get([MyApp, :meta, :language])
"elixir"