Crown.Oracle behaviour (crown v0.3.0)

Copy Markdown View Source

Behaviour for the external oracle used by Crown to determine leadership.

The oracle is the authority that grants and renews the crown. Implementations back this with an external service (database lease, Redis lock, etc.) so that leadership is enforced even across netsplits.

Callbacks

  • init/1 - called once at startup with the oracle options.
  • claim/1 - attempt to claim the crown. Returns {true, refresh_delay, state} on success, {false, state} otherwise. refresh_delay is a millisecond duration or :infinity.
  • refresh/1 - renew an already-held crown. Same return shape as claim/1.
  • abdicate/1 - optional. Called when the crown holder shuts down cleanly, allowing the oracle to release the claim early.
  • handle_info/2 - optional. Called when Crown receives an unexpected message, forwarding it to the oracle. Useful when monitor_leader: false and the oracle needs to react to external signals (e.g. a webhook) to trigger a claim attempt. Returns the same shape as claim/1 and refresh/1.

Summary

Callbacks

Release the crown on clean shutdown. Optional.

Attempt to claim the crown.

Handle an unexpected message forwarded by Crown. Optional.

Initialize the oracle with the given options.

Refresh an already-held crown.

Callbacks

abdicate(state)

(optional)
@callback abdicate(state :: term()) :: :ok

Release the crown on clean shutdown. Optional.

claim(state)

@callback claim(state :: term()) ::
  {true, refresh_delay :: non_neg_integer() | :infinity, new_state :: term()}
  | {false, new_state :: term()}

Attempt to claim the crown.

handle_info(msg, state)

(optional)
@callback handle_info(msg :: term(), state :: term()) ::
  {true, refresh_delay :: non_neg_integer() | :infinity, new_state :: term()}
  | {false, new_state :: term()}

Handle an unexpected message forwarded by Crown. Optional.

init(opts)

@callback init(opts :: keyword()) ::
  {:ok, state :: term()} | {:error, reason :: term()} | :ignore

Initialize the oracle with the given options.

When the options are a keyword list, Crown automatically injects a :crown_name key (via Keyword.put_new/3) containing the Crown instance name atom. Oracles can use this for namespacing (e.g. as a lock name).

refresh(state)

@callback refresh(state :: term()) ::
  {true, refresh_delay :: non_neg_integer() | :infinity, new_state :: term()}
  | {false, new_state :: term()}

Refresh an already-held crown.