Crank.Machine (Crank v0.2.0)

Copy Markdown View Source

The struct that Crank.crank/2 takes and returns.

%Crank.Machine{} carries five fields:

  • :module -- the callback module that defines the machine's transitions
  • :state -- the current state (any term: atoms, structs, tagged tuples)
  • :data -- data shared across all states, carried through every crank
  • :effects -- side effects from the last crank, stored as inert data
  • :status -- :running or {:stopped, reason}

The struct never executes side effects. It stores them. Crank.Server interprets and executes effects when the machine runs as a process. In pure code, inspect them directly.

Each call to Crank.crank/2 replaces the effects list. Effects from earlier cranks don't accumulate.

Parameterized types

t/0 is the generic type. For precise typing in your own modules, use t/2 with concrete state and data types:

@spec get_machine() :: Crank.Machine.t(:locked | :unlocked, map())

See Crank.Examples.Submission for the struct-per-state pattern, where each state is its own struct.

Summary

Types

Any gen_statem action that can appear in an effects list.

Fires if no event arrives within the given period.

A timeout identified by a caller-chosen name. Multiple named timeouts can run concurrently.

Injects a new event into the machine's own event queue.

Sends a reply to a caller waiting on Crank.Server.call/3.

Fires if the machine stays in the current state for the given period.

:running while the machine accepts events. {:stopped, reason} after it shuts down.

t()

A machine with generic (unparameterized) state and data types.

A machine parameterized by its state and data types.

Types

action()

@type action() ::
  :postpone
  | :hibernate
  | reply_action()
  | event_timeout()
  | state_timeout()
  | named_timeout()
  | next_event_action()

Any gen_statem action that can appear in an effects list.

event_timeout()

@type event_timeout() ::
  {:timeout, non_neg_integer() | :infinity, term()}
  | {:timeout, non_neg_integer() | :infinity, term(), keyword()}

Fires if no event arrives within the given period.

named_timeout()

@type named_timeout() ::
  {{:timeout, term()}, non_neg_integer() | :infinity, term()}
  | {{:timeout, term()}, non_neg_integer() | :infinity, term(), keyword()}

A timeout identified by a caller-chosen name. Multiple named timeouts can run concurrently.

next_event_action()

@type next_event_action() :: {:next_event, Crank.event_type(), term()}

Injects a new event into the machine's own event queue.

reply_action()

@type reply_action() :: {:reply, GenServer.from(), term()}

Sends a reply to a caller waiting on Crank.Server.call/3.

state_timeout()

@type state_timeout() ::
  {:state_timeout, non_neg_integer() | :infinity, term()}
  | {:state_timeout, non_neg_integer() | :infinity, term(), keyword()}

Fires if the machine stays in the current state for the given period.

status()

@type status() :: :running | {:stopped, reason :: term()}

:running while the machine accepts events. {:stopped, reason} after it shuts down.

t()

@type t() :: t(term(), term())

A machine with generic (unparameterized) state and data types.

t(state, data)

@type t(state, data) :: %Crank.Machine{
  data: data,
  effects: [action()],
  module: module(),
  state: state,
  status: status()
}

A machine parameterized by its state and data types.

@spec checkout_machine() :: Crank.Machine.t(:cart | :payment | :complete, Order.t())