Hume (hume v0.0.17)

Copy Markdown View Source

Hume is a library for building event-sourced state machines in Elixir.

It provides a framework for defining state machines that can handle events, maintain state, and take snapshots of their state for efficient recovery.

The library leverages Elixir's GenServer for process management and can use ETS for event storage. It also includes a mechanism for transferring ETS table ownership using a "heir" process.

Features

  • Define state machines using a simple behaviour.
  • Handle events and update state accordingly.
  • Persist events to an event store (in-memory or ETS).
  • Take snapshots of the current state for efficient recovery.
  • Transfer ETS table ownership using a dedicated heir process.

Getting Started

To get started with Hume, you can define a state machine by creating a module that uses Hume.Projection and implements the required callbacks. You can then start the state machine process and send events to it.

Example

defmodule MyProjection do
  use Hume.Projection, use_ets: true, store: Hume.EventStore.ETS

  @impl true
  def init_state(_), do: %{}

  @impl true
  def handle_event({:add, key, value}, state),
    do: {:ok, Map.put(state || %{}, key, value)}

  @impl true
  def handle_event({:remove, key}, state),
    do: {:ok, Map.delete(state || %{}, key)}
end

Hume.EventStore.ETS.start_link([])
{:ok, pid} = Hume.start_link(MyProjection, stream: MyStream, projection: MyProjection)

{:ok, _} = Hume.publish(Hume.EventStore.ETS, MyStream, {:add, :foo, 42})
%{foo: 42} = Hume.state(pid)
{:ok, _} = Hume.publish(Hume.EventStore.ETS, MyStream, {:remove, :foo})
%{} = Hume.state(pid)

Summary

Functions

Publishes an event to the specified event store and stream.

Starts a state machine process without linking it to the current process.

Starts a state machine process.

Types

snapshot_opts()

@type snapshot_opts() :: {:timeout, timeout()} | :dirty

Functions

publish(event_store, stream, payload, opts \\ [])

@spec publish(
  event_store :: module(),
  Hume.EventStore.stream(),
  Hume.EventStore.payload(),
  [Hume.Publisher.options()]
) :: {:ok, non_neg_integer()} | {:error, term()}

Publishes an event to the specified event store and stream.

Parameters

  • event_store: The module implementing the event store (must use Hume.EventStore).
  • stream: The stream identifier where the event will be published.
  • payload: The event payload to be published.
  • opts: Optional keyword list of options. Supported options:
    • :expect_seq - The expected sequence number for optimistic concurrency control.

Returns

  • {:ok, seq} if the event is published successfully.
  • {:error, reason} if there is an error during publishing.

snapshot(server, opts \\ [])

See Hume.Projection.snapshot/2.

start(mod, opts \\ [])

Starts a state machine process without linking it to the current process.

See Hume.start_link/2 for options and return values.

start_link(mod, opts \\ [])

@spec start_link(module(), [Hume.Projection.option()]) :: GenServer.on_start()

Starts a state machine process.

Options

  • :stream - The stream identifier (required).
  • :projection - The unique name for the projection (optional).

Returns

  • {:ok, pid} if the process starts successfully.
  • {:error, reason} if the process fails to start.

state(server, opts \\ [])

See Hume.Projection.state/2.