Chronicle.ReadModels.ReadModel (cratis_chronicle v1.0.3)

Copy Markdown View Source

Macro for defining Chronicle read models with embedded model-bound projections.

Use Chronicle.ReadModels.ReadModel in a struct module to define both the read model shape and how Chronicle should project events into it. The projection definition lives right next to the struct fields — no separate projection module is needed.

Quick Example

defmodule MyApp.ReadModels.Account do
  use Chronicle.ReadModels.ReadModel

  defstruct account_id: nil, owner_name: nil, balance: 0, transaction_count: 0

  from MyApp.Events.AccountOpened,
    set: [
      account_id: :event_source_id,
      owner_name: :owner_name,
      balance: :initial_balance
    ]

  from MyApp.Events.FundsDeposited,
    add: [balance: :amount, transaction_count: 1]

  from MyApp.Events.FundsWithdrawn,
    subtract: [balance: :amount],
    add: [transaction_count: 1]
end

Projection Macros

from/2

Maps properties from an event onto the read model.

from MyApp.Events.AccountOpened,
  set: [account_id: :event_source_id, owner_name: :owner_name],
  count: :transaction_count

Options:

  • :key — key expression identifying the model instance. Defaults to "$eventSourceId" when omitted.
  • :parent_key — parent key for nested models
  • :set — keyword list of field: expression pairs to set directly
  • :add — keyword list of field: expression pairs to add to
  • :subtract — keyword list of field: expression pairs to subtract from
  • :count — field atom to increment by 1 on each event occurrence

join/2

Joins a secondary event onto the model by a matching field.

join MyApp.Events.AccountVerified,
  on: "accountId",
  set: [verified: true]

Options:

  • :on(required) the field name in the event to join on
  • :key — key expression (defaults to "$eventSourceId")
  • :set, :add, :subtract — property mappings

removed_with/2

Removes the model instance when the given event occurs.

removed_with MyApp.Events.AccountClosed,
  []

Options:

  • :key — key expression (defaults to "$eventSourceId")
  • :parent_key — parent key for nested models

from_every/1

Applies property mappings on every event, regardless of type.

from_every set: [last_activity: "Occurred"]

Options:

  • :set, :add, :subtract — property mappings applied to every event

Property Expressions

Values in set:, add:, and subtract: lists can be atoms, strings, or literals:

  • Use atoms for event fields (preferred): :owner_name, :amount
  • Use :event_source_id and :occurred for built-in context values
  • Use strings for advanced Chronicle expressions when needed
  • Use numbers and booleans as literal values
ExpressionMeaning
:owner_nameThe owner_name field from the event
:event_source_idThe event source identifier
:occurredWhen the event was recorded
1A literal integer constant
"$add(amount, balance)"An explicit Chronicle expression

Registering with Chronicle.Client

{Chronicle.Client,
  ...
  read_models: [MyApp.ReadModels.Account]}

Introspection

MyApp.ReadModels.Account.__chronicle_read_model__(:id)
MyApp.ReadModels.Account.__chronicle_read_model__(:from)
MyApp.ReadModels.Account.__chronicle_read_model__(:join)
MyApp.ReadModels.Account.__chronicle_read_model__(:removed_with)
MyApp.ReadModels.Account.__chronicle_read_model__(:from_every)
MyApp.ReadModels.Account.__chronicle_read_model__(:has_projection?)
MyApp.ReadModels.Account.__chronicle_read_model__(:passive?)

Passive Read Models

Pass passive: true to mark a read model as passive. A passive projection does not actively observe events and never writes to a materialized sink — its instances are resolved on demand via immediate projection when looked up by id. This is useful for read models that only need to be queried by key (for example, from within a reactor).

defmodule MyApp.ReadModels.Application do
  use Chronicle.ReadModels.ReadModel, passive: true

  defstruct id: nil, name: nil

  from MyApp.Events.ApplicationCreated,
    set: [id: :event_source_id, name: :name]
end

Summary

Functions

Declares how an event maps onto this read model.

Applies property mappings on every event, regardless of type.

Declares a join from a secondary event onto this read model.

Declares that this model is removed when the given event occurs.

Functions

from(event_module, opts \\ [])

(macro)

Declares how an event maps onto this read model.

See the Chronicle.ReadModels.ReadModel module documentation for full options.

from_every(opts)

(macro)

Applies property mappings on every event, regardless of type.

See the Chronicle.ReadModels.ReadModel module documentation for full options.

join(event_module, opts)

(macro)

Declares a join from a secondary event onto this read model.

See the Chronicle.ReadModels.ReadModel module documentation for full options.

removed_with(event_module, opts \\ [])

(macro)

Declares that this model is removed when the given event occurs.

See the Chronicle.ReadModels.ReadModel module documentation for full options.