Macro for defining Chronicle declarative projections.
A declarative projection is a standalone module that defines how events map onto
a read model. Unlike model-bound projections — where from declarations live
directly inside the read model module — a declarative projection keeps the read
model as a pure data structure while the projection logic lives in a separate module.
Quick Example
defmodule MyApp.Projections.AccountSummaryProjection do
use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountSummary
from MyApp.Events.AccountOpened,
set: [
account_id: :event_source_id,
owner_name: :owner_name,
balance: :initial_balance
]
from MyApp.Events.FundsDeposited,
add: [balance: :amount]
from MyApp.Events.FundsWithdrawn,
subtract: [balance: :amount]
endThe read model (AccountSummary) is a plain struct using use Chronicle.ReadModels.ReadModel
with no from declarations — it is a pure data shape, not a projection definition.
Options
:model— (required) the read model module this projection writes into.:id— identifier string for this projection. Defaults to the last segment of the module name (e.g."AccountSummaryProjection"). A defaulted id (pin it explicitly to silence this) emits a one-time warning when discovered — seeChronicle.Discovery.DefaultedIdWarning.:passive— whentrue, the projection does not actively observe events and never writes to a materialized sink; its read model is resolved on demand via immediate projection when looked up by id. Defaults tofalse.
Projection Macros
The following macros are available and carry the same options as their counterparts
in Chronicle.ReadModels.ReadModel:
from/1,from/2— maps properties from an event onto the read model.join/2— joins a secondary event onto the model by a matching field.removed_with/1,removed_with/2— removes the model instance when the given event occurs.removed_with_join/1,removed_with_join/2— removes the model instance when a secondary event matches it by a property instead of by its own key.clear_with/2,clear_with/3— sets a field back to no value; sugar forfrom event, clear: [...].from_every/1— applies property mappings on every event, regardless of type.variant_of/2— declares this projection to be one of several mutually exclusive representations of the same logical entity. SeeChronicle.ReadModels.ReadModel.enters_on/1,enters_on/2— names the event(s) that may create or resurrect this variant.
Registering with Chronicle.Client
{Chronicle.Client,
...
projections: [MyApp.Projections.AccountSummaryProjection]}Or use otp_app: auto-discovery — modules that export __chronicle_projection__/1
are discovered automatically.
Introspection
MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:id)
MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:id_source)
MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:model)
MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:from)
MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:join)
MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:removed_with)
MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:from_every)
Summary
Functions
Sets a field back to no value when the given event occurs. Sugar for from event, clear: [...].
Names an event that may create or resurrect this projection's variant. See
Chronicle.ReadModels.ReadModel.enters_on/2 for full documentation.
Declares how an event maps onto the read model.
Applies property mappings on every event, regardless of type.
Declares a join from a secondary event onto the read model.
Declares that the read model instance is removed when the given event occurs.
Declares that the read model instance is removed when a secondary event matches it by a property, instead of by its own key.
Declares this projection to be one of several mutually exclusive representations of the same
logical entity. See Chronicle.ReadModels.ReadModel.variant_of/2 for full documentation.
Functions
Sets a field back to no value when the given event occurs. Sugar for from event, clear: [...].
See Chronicle.ReadModels.ReadModel for full options documentation.
Names an event that may create or resurrect this projection's variant. See
Chronicle.ReadModels.ReadModel.enters_on/2 for full documentation.
Declares how an event maps onto the read model.
See Chronicle.ReadModels.ReadModel for full options documentation.
Applies property mappings on every event, regardless of type.
Supports dictionary fields keyed by event context values:
from_every increment: [event_counts: {:event_context, :type}]See Chronicle.ReadModels.ReadModel for full options documentation.
Declares a join from a secondary event onto the read model.
See Chronicle.ReadModels.ReadModel for full options documentation.
Declares that the read model instance is removed when the given event occurs.
See Chronicle.ReadModels.ReadModel for full options documentation.
Declares that the read model instance is removed when a secondary event matches it by a property, instead of by its own key.
See Chronicle.ReadModels.ReadModel for full options documentation.
Declares this projection to be one of several mutually exclusive representations of the same
logical entity. See Chronicle.ReadModels.ReadModel.variant_of/2 for full documentation.