Chronicle (chronicle v0.0.1)

Copy Markdown View Source

Idiomatic Elixir client for the Chronicle event-sourcing platform.

Chronicle is an event-sourcing kernel that stores domain events and projects them into read models. This library provides an idiomatic Elixir interface built on top of the Chronicle gRPC API.

Quick Start

Add the dependency to your mix.exs:

{:chronicle, "~> 0.1", organization: "cratis"}

Start Chronicle.Client in your application supervision tree:

defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      {Chronicle.Client,
        connection_string: "chronicle://localhost:35000?disableTls=true",
        event_store: "my-app",
        event_types: [MyApp.Events.AccountOpened, MyApp.Events.FundsDeposited],
        reactors: [MyApp.Reactors.NotificationReactor],
        reducers: [MyApp.Reducers.AccountReducer]}
    ]

    Supervisor.start_link(children, strategy: :one_for_one)
  end
end

Defining Event Types

defmodule MyApp.Events.AccountOpened do
  use Chronicle.EventType, id: "account-opened-v1"
  defstruct [:account_id, :owner_name, :initial_balance]
end

Appending Events

Chronicle.append("account-42", %MyApp.Events.AccountOpened{
  account_id: "account-42",
  owner_name: "Alice",
  initial_balance: 1000
})

Reading Read Models

{:ok, account} = Chronicle.read_model(MyApp.ReadModels.Account, "account-42")

Defining Reactors

defmodule MyApp.Reactors.NotificationReactor do
  use Chronicle.Reactor

  @handles MyApp.Events.AccountOpened

  @impl true
  def handle(%MyApp.Events.AccountOpened{} = event, _context) do
    MyApp.Mailer.welcome(event.owner_name)
    :ok
  end
end

Defining Reducers

defmodule MyApp.Reducers.AccountReducer do
  use Chronicle.Reducer, model: MyApp.ReadModels.Account

  @handles MyApp.Events.AccountOpened

  @impl true
  def reduce(%MyApp.Events.AccountOpened{} = event, _model, _context) do
    %MyApp.ReadModels.Account{
      account_id: event.account_id,
      owner_name: event.owner_name,
      balance: event.initial_balance
    }
  end
end

Modules

Summary

Functions

Returns all instances of the given read model.

Appends a single event to the event log for the given event source.

Appends multiple events to the event log for the given event source.

Fetches a read model instance by its key (typically an event source ID).

Functions

all(model_module, opts \\ [])

@spec all(
  module(),
  keyword()
) :: {:ok, [struct()]} | {:error, term()}

Returns all instances of the given read model.

Delegates to Chronicle.ReadModels.all/2.

append(event_source_id, event, opts \\ [])

@spec append(String.t(), struct(), keyword()) :: :ok | {:error, term()}

Appends a single event to the event log for the given event source.

Delegates to Chronicle.EventLog.append/3.

Options

  • :client — the client name (default: Chronicle.Client)
  • :namespace — overrides the client's default namespace
  • :tags — list of tag strings
  • :subject — the identity subject string

append_many(event_source_id, events, opts \\ [])

@spec append_many(String.t(), [struct()], keyword()) :: :ok | {:error, term()}

Appends multiple events to the event log for the given event source.

Delegates to Chronicle.EventLog.append_many/3.

read_model(model_module, key, opts \\ [])

@spec read_model(module(), String.t(), keyword()) ::
  {:ok, struct() | nil} | {:error, term()}

Fetches a read model instance by its key (typically an event source ID).

Delegates to Chronicle.ReadModels.get/3.

Returns {:ok, model_struct} on success, or {:ok, nil} if not found.