Release v3.4.0
Ports Chronicle's read model variations feature (Cratis/Chronicle#3956, shipped for the .NET
client in Cratis/Chronicle#4062, and for Kotlin/Java and TypeScript in
Cratis/Chronicle.Kotlin#85 and Cratis/Chronicle.TypeScript#75) to the Elixir client, with
documentation snippets for both authoring styles.
Added
Both Chronicle.ReadModels.ReadModel (model-bound) and Chronicle.Projections.Projection
(declarative) gain two new macros:
variant_of/2declares a read model or projection to be one of several mutually exclusive
representations of the same logical entity. Entering one variant removes the entity from every
sibling variant.enters_on/1,2names the event(s) that may create or resurrect a variant. Every other event a
variant projects from — whether viafrom/2directly or merged in from a global handler — is
automatically reclassified into an update-only join, so it can update an already-active
instance but can never create or resurrect one.
A new Chronicle.Projections.GlobalHandler macro shares a mapping across every variant of a
group without repeating it on each variant module. A mapping that targets a member some variant
lacks is a declaration error (GlobalHandlerPropertyNotOnVariant), not a silently skipped
mapping. A global handler module is discovered through a new __chronicle_global_handler__/1
introspection function and the Chronicle.Client :global_handlers option, and is never
registered as its own projection.
Chronicle.Projections.VariantReclassifier applies the same merge-then-reclassify-then-cross-wire
pipeline as the other clients, operating on the already-built ProjectionDefinition structs
shared by both authoring styles.
Note on current kernel support
A variant's own key is what the reclassified self-join correlates on. The kernel does not honor
$eventSourceId in a property mapping yet (Cratis/Chronicle#3924 — a pre-existing gap that
already affects from/2's :key/:event_source_id generally, not something introduced here).
The definition shape this ships is otherwise complete and verified; it starts working end-to-end
the day that is fixed, with no changes needed on this side.