RaftEx.Machine behaviour (raft_ex v0.1.0)

View Source

Behaviour for RaftEx state machines.

Implement init/1 and apply/3 as mandatory callbacks. All other callbacks (tick, state_enter, snapshot hooks, versioning, etc.) are optional — sensible defaults are used when they are absent.

Effects

apply/3 may return a third element containing one or more effects that the Raft framework will execute after the entry is applied. Effects are described by effect/0.

Summary

Types

command_meta()

@type command_meta() :: %{
  optional(:machine_version) => version(),
  optional(:from) => term(),
  optional(:reply_mode) => term(),
  system_time: integer(),
  index: non_neg_integer(),
  term: non_neg_integer()
}

effect()

@type effect() ::
  {:send_msg, to :: term(), msg :: term()}
  | {:send_msg, to :: term(), msg :: term(), opts :: term()}
  | {:mod_call, module(), atom(), [term()]}
  | {:append, cmd :: term()}
  | {:append, cmd :: term(), reply_mode :: term()}
  | {:monitor, :process, pid()}
  | {:monitor, :node, node()}
  | {:demonitor, :process, pid()}
  | {:demonitor, :node, node()}
  | {:timer, term(), non_neg_integer() | :infinity}
  | {:release_cursor, RaftEx.Types.index(), state()}
  | {:release_cursor, RaftEx.Types.index(), state(), map()}
  | {:release_cursor, RaftEx.Types.index()}
  | {:checkpoint, RaftEx.Types.index(), state()}
  | {:aux, term()}
  | :garbage_collection

effects()

@type effects() :: [effect()]

machine()

@type machine() :: {:machine, module(), map()}

milliseconds()

@type milliseconds() :: non_neg_integer()

reply()

@type reply() :: term()

state()

@type state() :: term()

user_command()

@type user_command() :: term()

version()

@type version() :: non_neg_integer()

Callbacks

apply(command_meta, command, state)

@callback apply(command_meta(), command :: term(), state()) ::
  {state(), reply(), effects() | effect()} | {state(), reply()}

handle_aux(ra_state, type, cmd, aux_state, internal)

(optional)
@callback handle_aux(
  ra_state :: atom(),
  type :: term(),
  cmd :: term(),
  aux_state :: term(),
  internal :: term()
) ::
  {:reply, term(), term(), term()}
  | {:reply, term(), term(), term(), effects()}
  | {:no_reply, term(), term()}
  | {:no_reply, term(), term(), effects()}

handle_aux(ra_state, type, cmd, aux_state, log, mac_state)

(optional)
@callback handle_aux(
  ra_state :: atom(),
  type :: term(),
  cmd :: term(),
  aux_state :: term(),
  log :: term(),
  mac_state :: state()
) :: {:reply, term(), term(), term()} | {:no_reply, term(), term()}

init(conf)

@callback init(conf :: map()) :: state()

init_aux(name)

(optional)
@callback init_aux(name :: atom()) :: term()

live_indexes(state)

(optional)
@callback live_indexes(state()) :: [RaftEx.Types.index()] | {:ra_seq, term()}

overview(state)

(optional)
@callback overview(state()) :: map()

snapshot_installed(meta, state, old_meta, old_state)

(optional)
@callback snapshot_installed(
  meta :: map(),
  state(),
  old_meta :: map(),
  old_state :: state()
) :: effects()

snapshot_module()

(optional)
@callback snapshot_module() :: module()

state_enter(ra_state, state)

(optional)
@callback state_enter(ra_state :: atom(), state()) :: effects()

tick(milliseconds, state)

(optional)
@callback tick(milliseconds(), state()) :: effects()

version()

(optional)
@callback version() :: version()

which_module(version)

(optional)
@callback which_module(version()) :: module()

Functions

apply(mod, metadata, cmd, state)

@spec apply(module(), command_meta(), term(), state()) ::
  {state(), reply(), effects()}

handle_aux(mod, raft_state, type, cmd, aux, state)

@spec handle_aux(module(), atom(), term(), term(), term(), term()) :: term()

handle_aux(mod, raft_state, type, cmd, aux, log, mac_state)

@spec handle_aux(module(), atom(), term(), term(), term(), term(), term()) :: term()

init(machine, name, version)

@spec init(machine(), atom(), version()) :: state()

init_aux(mod, name)

@spec init_aux(module(), atom()) :: term()

is_versioned(arg)

@spec is_versioned(machine()) :: boolean()

live_indexes(mod, state)

@spec live_indexes(module(), state()) :: term()

module(arg)

@spec module(machine()) :: module()

overview(mod, state)

@spec overview(module(), state()) :: map()

query(mod, fun, state, ctx \\ %{})

@spec query(module(), fun() | {module(), atom(), list()}, state(), map()) :: term()

snapshot_installed(mod, meta, state, old_meta, old_state)

@spec snapshot_installed(module(), map(), state(), map(), state()) :: effects()

snapshot_module(arg)

@spec snapshot_module(machine()) :: module()

state_enter(mod, raft_state, state)

@spec state_enter(module(), atom(), state()) :: effects()

tick(mod, time_ms, state)

@spec tick(module(), milliseconds(), state()) :: effects()

version(mod)

@spec version(module() | machine()) :: version()

which_aux_fun(mod)

@spec which_aux_fun(module()) :: {:handle_aux, 5 | 6} | nil

Determine which arity of handle_aux the module exports (5 or 6 args), returning {:handle_aux, arity} or nil if neither is exported.

which_module(arg, version)

@spec which_module(machine(), version()) :: module()