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:
{:cratis_chronicle, "~> 0.1"}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],
migrations: [MyApp.Migrations.AccountOpenedV2Migration],
reactors: [MyApp.Reactors.NotificationReactor],
reducers: [MyApp.Reducers.AccountReducer],
seeders: [MyApp.Seeders.InitialDataSeeder],
event_store_subscriptions: [
MyApp.EventStoreSubscriptions.DefaultAccountEvents
]}
]
Supervisor.start_link(children, strategy: :one_for_one)
end
endOr rely on artifact auto-discovery:
{Chronicle.Client,
connection_string: "chronicle://localhost:35000?disableTls=true",
event_store: "my-app",
otp_app: :my_app}Defining Event Types
defmodule MyApp.Events.AccountOpened do
use Chronicle.Events.EventType, id: "account-opened-v1"
defstruct [:account_id, :owner_name, :initial_balance]
endAppending 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.Reactors.Reactor
@handles MyApp.Events.AccountOpened
@impl true
def handle(%MyApp.Events.AccountOpened{} = event, _context) do
MyApp.Mailer.welcome(event.owner_name)
:ok
end
endDefining Reducers
defmodule MyApp.Reducers.AccountReducer do
use Chronicle.Reducers.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
endDefining Seeders
defmodule MyApp.Seeders.InitialDataSeeder do
use Chronicle.Seeding.Seeder
@impl true
def seed(builder) do
builder
|> Chronicle.Seeding.for(
MyApp.Events.AccountOpened,
"seed-account-1",
[%MyApp.Events.AccountOpened{
account_id: "seed-account-1",
owner_name: "Initial User",
initial_balance: 10_000
}]
)
end
endModules
Chronicle.Client— the main supervisor; start it in your supervision treeChronicle.Correlation.CorrelationId/Chronicle.Correlation.CorrelationIdManager— correlate operationsChronicle.Identity/Chronicle.Identity.IdentityProvider— track who caused state changesChronicle.Auditing.CausationType,Chronicle.Auditing.CausationEntry,Chronicle.Auditing.CausationManager— audit causation chainsChronicle.Events.EventType— macro for defining event typesChronicle.Events.Migration— macro for defining event migrationsChronicle.Events.MigrationBuilder— fluent API for migration transformsChronicle.Events.Migrators— migration discovery and registration supportChronicle.Events.ConcurrencyScope— scope optimistic concurrency checks for appendsChronicle.Reactors.Reactor— behaviour for event reactorsChronicle.Reducers.Reducer— behaviour for read model reducersChronicle.Seeding.Seeder— behaviour for event seedersChronicle.EventStoreSubscriptions— register event store subscriptionsChronicle.EventStoreSubscriptions.Subscription— define discoverable event store subscriptionsChronicle.ReadModels.ReadModel— macro for read model structs with embedded projection DSLChronicle.EventSequences.EventLog— append and query eventsChronicle.EventSequences.EventSequence— work with custom event sequencesChronicle.Transactions.UnitOfWork— buffer and commit transactional appendsChronicle.EventStores— list event stores and namespacesChronicle.ReadModels— query read model instancesChronicle.Jobs— inspect and control Chronicle jobsChronicle.WebHooks— inspect and register webhooksChronicle.Connections.ConnectionString— parse and format connection stringsChronicle.Connections.Connection— resilient gRPC channel management
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.
Begins a new unit of work for the calling process.
Clears the current process correlation id.
Clears the current process identity.
Gets the current process correlation id.
Gets the current process identity.
Returns the current unit of work for the calling process.
Deletes a Chronicle job.
Creates an event sequence wrapper for the given event sequence id.
Returns all event store names.
Gets a single Chronicle job by identifier.
Gets all steps for a Chronicle job.
Gets all jobs for the configured event store namespace.
Returns all namespaces for an event store.
Gets the tail sequence number for an event sequence.
Gets all registered webhooks.
Checks whether there are events for an event source id in an event sequence.
Fetches a read model instance by its key (typically an event source ID).
Registers all discoverable event store subscriptions.
Registers all discoverable webhooks.
Registers a discoverable event store subscription module.
Registers a discoverable webhook module.
Registers a webhook imperatively.
Removes a registered webhook by identifier.
Resumes a Chronicle job.
Sets the current process correlation id.
Sets the current process identity.
Stops a Chronicle job.
Registers an event store subscription imperatively using all available event types.
Registers an event store subscription imperatively.
Removes an event store subscription by identifier.
Runs a function inside a unit of work and commits it if the function succeeds.
Functions
Returns all instances of the given read model.
Delegates to Chronicle.ReadModels.all/2.
Appends a single event to the event log for the given event source.
Delegates to Chronicle.EventSequences.EventLog.append/3.
Options
:client— the client name (default:Chronicle.Client):namespace— overrides the client's default namespace:event_sequence_id— event sequence id (default:"event-log"):tags— list of tag strings:subject— the identity subject string:correlation_id—Chronicle.Correlation.CorrelationId(or id string) override:identity—Chronicle.Identityoverride:causation— list ofChronicle.Auditing.CausationEntryoverrides:concurrency_scope—Chronicle.Events.ConcurrencyScopeor keyword options
Appends multiple events to the event log for the given event source.
Delegates to Chronicle.EventSequences.EventLog.append_many/3.
Accepts the same append options as append/3, including :concurrency_scope.
@spec begin_unit_of_work(keyword()) :: Chronicle.Transactions.UnitOfWork.t()
Begins a new unit of work for the calling process.
@spec clear_correlation_id() :: Chronicle.Correlation.CorrelationId.t()
Clears the current process correlation id.
@spec clear_identity() :: :ok
Clears the current process identity.
@spec current_correlation_id() :: Chronicle.Correlation.CorrelationId.t()
Gets the current process correlation id.
@spec current_identity() :: Chronicle.Identity.t()
Gets the current process identity.
@spec current_unit_of_work() :: Chronicle.Transactions.UnitOfWork.t()
Returns the current unit of work for the calling process.
Deletes a Chronicle job.
@spec event_sequence( String.t(), keyword() ) :: Chronicle.EventSequences.EventSequence.t()
Creates an event sequence wrapper for the given event sequence id.
Returns all event store names.
@spec get_job( String.t(), keyword() ) :: {:ok, Chronicle.Jobs.Job.t() | nil} | {:error, term()}
Gets a single Chronicle job by identifier.
@spec get_job_steps( String.t(), keyword() ) :: {:ok, [Chronicle.Jobs.JobStep.t()]} | {:error, term()}
Gets all steps for a Chronicle job.
@spec get_jobs(keyword()) :: {:ok, [Chronicle.Jobs.Job.t()]} | {:error, term()}
Gets all jobs for the configured event store namespace.
Returns all namespaces for an event store.
Uses the configured client event store by default.
@spec get_tail_sequence_number( String.t() | nil, keyword() ) :: {:ok, non_neg_integer()} | {:error, term()}
Gets the tail sequence number for an event sequence.
@spec get_webhooks(keyword()) :: {:ok, [Chronicle.WebHooks.Definition.t()]} | {:error, term()}
Gets all registered webhooks.
Checks whether there are events for an event source id in an event sequence.
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.
Registers all discoverable event store subscriptions.
Registers all discoverable webhooks.
Registers a discoverable event store subscription module.
Registers a discoverable webhook module.
@spec register_webhook( String.t(), String.t(), (Chronicle.WebHooks.DefinitionBuilder.t() -> Chronicle.WebHooks.DefinitionBuilder.t()), keyword() ) :: :ok | {:error, term()}
Registers a webhook imperatively.
Removes a registered webhook by identifier.
Resumes a Chronicle job.
@spec set_correlation_id(Chronicle.Correlation.CorrelationId.t() | String.t()) :: Chronicle.Correlation.CorrelationId.t()
Sets the current process correlation id.
@spec set_identity(Chronicle.Identity.t()) :: Chronicle.Identity.t()
Sets the current process identity.
Stops a Chronicle job.
Registers an event store subscription imperatively using all available event types.
@spec subscribe_to_event_store( String.t(), String.t(), (Chronicle.EventStoreSubscriptions.DefinitionBuilder.t() -> Chronicle.EventStoreSubscriptions.DefinitionBuilder.t()), keyword() ) :: :ok | {:error, term()}
Registers an event store subscription imperatively.
Removes an event store subscription by identifier.
@spec with_unit_of_work( (Chronicle.Transactions.UnitOfWork.t() -> any()), keyword() ) :: any()
Runs a function inside a unit of work and commits it if the function succeeds.