Repository navigation
Release v3.13.0
The Elixir client catches up with the .NET client on decision reads, captures, testing, constraints, projections, concurrency and observability. Everything is additive: existing code compiles and behaves as before.
Added
- Decision reads for the dynamic consistency boundary.
Chronicle.ReadModels.DecisionReadsget/2,get_detached/2,admit/2and their stream-scoped variants enroll a read into the unit of work, andChronicle.decide/2commits it, returning{:error, %Chronicle.ReadModels.DecisionConflict{}}when a concurrent append invalidated the read. Passive reducers can be read this way too. See Dynamic Consistency Boundary. (#140) Chronicle.Testing: an in-memory kernel with concurrency and constraint checks, in-process reactors and reducers,wait_for_observers/1,assert_appended/refute_appended,Chronicle.Testing.Case, an isolated-store helper for integration specs, andChronicle.Behaviourso theChroniclefacade can be mocked with Mox. See Testing. (#149)- Captures:
use Chronicle.Captures.Capturedeclares a capture that compiles to Capture Declaration Language, with compile-time errors for a missing source, key or append condition.Chronicle.Capturesregisters, starts, stops, lists and validates captures, and the client registers them throughcaptures:orotp_app:discovery. (#148) - Discovery report and artifact identity drift:
Chronicle.Client.discovery_report/1,identity_drift/1, adrift_policy: :ignore | :warn | :failoption (default:warn, never fails startup), a one-time warning for reactor, reducer and projection ids defaulted from the module name, andmix chronicle.discover. (#147) - Standalone constraint modules with
use Chronicle.Events.Constraint, registered throughconstraints:or discovery, plusremove_constraint/2with per-value removal properties,:scopeand:event_sequencesonunique_event_type, violation message callbacks, andChronicle.Events.ConstraintViolation.details/1. (#143) - Projections: a one-line
childrenform,removed_with_join/2,clear_with/2, a default:onfor joins insidechildren, and compile-time errors for a rootjoinwithout:on, a duplicate property target and an unknown field. (#127) - Read models: shared, self-reconnecting subscriptions with
Chronicle.ReadModels.subscribe/2andunsubscribe/1,:filterand:sortonobserve/2,observe_stream/2, andChronicle.Projections.query/2,preview/2andwait_for/3. (#144) ConcurrencyScopepipe helpers (with_sequence_number/2,with_event_types/2,with_event_stream_id/2and more) andat_tail/2, and an opt-in client-wideconcurrency: [default: :optimistic, check_first_append: true]strategy. (#134)- Prepared events with
EventLog.prepare/2andappend_prepared/3,get_metadata_at/2, andinitiator_typeandresolved_caused_byin event metadata. (#150) generation_for:onuse Chronicle.Events.EventTypedeclares a generation of another event type, and thestrict_validation: trueclient option rejects duplicate event type generations and migrators at startup. (#146)- Pinned generation delivery for reactors and reducers with
generation_delivery: :pinned, or client-wide withevent_generation_delivery:. (#119) Chronicle.Patternsqueries behavior patterns, includingget_patterns_at/3for a moment andtime_bucket/1, which uses the same rule the engine mines with. (#39)- OpenTelemetry spans and
:telemetryevents for appends, reactors and reducers, and W3C trace context on every gRPC call, following the shared Cratis convention. The package now depends onopentelemetry_api; spans are only exported when your application installs an OpenTelemetry SDK. See Observability. (#96)
Changed
- Read model reactors share one kernel stream per read model and reconnect with backoff instead of re-watching on a fixed timer. (#144)
- Duplicate event type generations and duplicate migrators are now reported as errors in the log at startup. (#146)
- The Elixir documentation shows real snippets for many more shared Chronicle pages, including testing, child collections, composite keys, constraints and concurrency, and the Elixir pages now cover the features above. (#40)
Fixed
unique_event_typeconstraints are now registered with their event type; the kernel previously received an empty event type list. (#143)- Appending a struct that is not an event type returns
{:error, {:unknown_event_type, module}}instead of raising. (#150) - A batch with two different explicit concurrency scopes for the same event source returns
{:error, {:duplicate_concurrency_scope, event_source_id}}instead of silently dropping one guard. (#134) - Webhooks registered with
not_replayable()ornot_active()are now honored by Chronicle 19.33 and later. (#113) watch/2andobserve/2stop their kernel stream when the subscribing process exits. (#144)- API keys and OAuth bearer tokens no longer appear in the crash report of a failed gRPC response process. (part of #79)