structured_io v1.2.0 StructuredIO.GenServerTransaction View Source

Implements transactional changes to GenServer state.

You can call transaction/3 directly, but this module is better incorporated into a GenServer via the use directive. Doing so defines a public function in your module according to the following options:

  • :function_name — the name of the function to be defined in your module; defaults to transaction
  • :server_name — the name of the first parameter in the defined function; defaults to server
  • :commit_instruction — the commit_instruction/0 expected from an operation/0 passed to the function; defaults to :commit
  • :append_to_doc — content to be appended to the defined function’s default @doc attribute, such as example code
  • :since — the version expression to be assigned to the defined function’s @since attribute

Examples

iex> defmodule Counter do
...>   use GenServer
...>   use StructuredIO.GenServerTransaction, server_name: "counter"
...>
...>
...>   def start_link, do: GenServer.start_link(__MODULE__, 0)
...>
...>
...>   def current(counter), do: GenServer.call(counter, :current)
...>
...>
...>   def increment(counter), do: GenServer.call(counter, :increment)
...>
...>
...>   def handle_call(:current, _from, current=state), do: {:reply, current, state}
...>
...>
...>   def handle_call(:increment, _from, current=_state) do
...>     new_state = current + 1
...>     {:reply, current, new_state}
...>   end
...>
...>
...>   def init(argument) when is_integer(argument), do: {:ok, argument}
...> end
iex> {:ok,
...>  counter} = Counter.start_link
iex> Counter.current counter
0
iex> Counter.increment counter
iex> Counter.current counter
1
iex> Counter.transaction counter,
...>                     fn c ->
...>   1 = Counter.current(c)
...>
...>   Counter.increment c
...>   2 = Counter.current(c)
...>
...>   {:commit, :this_is_a_success}
...> end
:this_is_a_success
iex> Counter.current counter
2
iex> Counter.transaction counter,
...>                     fn c ->
...>   2 = Counter.current(c)
...>
...>   Counter.increment c
...>   3 = Counter.current(c)
...>
...>   {:this, :is, :a, :failure}
...> end
{:this, :is, :a, :failure}
iex> Counter.current counter
2

Link to this section Summary

Types

The label of a tuple returned from operation/0 that indicates it was successful

A function around which transactional behavior will be wrapped

Functions

Invokes the specified operation, changing the state of the specified server only if the operation is successful. Success is indicated when the operation returns {commit_instruction, term} (where commit_instruction is as specified), in which case only the term is returned

Link to this section Types

Link to this type commit_instruction() View Source
commit_instruction() :: atom()

The label of a tuple returned from operation/0 that indicates it was successful.

Link to this type operation() View Source
operation() :: (GenServer.server() -> {commit_instruction(), any()} | any())

A function around which transactional behavior will be wrapped.

Link to this section Functions

Link to this function transaction(server, commit_instruction, operation, timeout \\ 5000) View Source

Invokes the specified operation, changing the state of the specified server only if the operation is successful. Success is indicated when the operation returns {commit_instruction, term} (where commit_instruction is as specified), in which case only the term is returned.

Note: Within the operation, you must not send messages to the server. Send messages instead to the GenServer.server/0 which is an argument to the operation.