Skip to content

Release v3.13.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 17:46
e4429ac

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.DecisionReads get/2, get_detached/2, admit/2 and their stream-scoped variants enroll a read into the unit of work, and Chronicle.decide/2 commits 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, and Chronicle.Behaviour so the Chronicle facade can be mocked with Mox. See Testing. (#149)
  • Captures: use Chronicle.Captures.Capture declares a capture that compiles to Capture Declaration Language, with compile-time errors for a missing source, key or append condition. Chronicle.Captures registers, starts, stops, lists and validates captures, and the client registers them through captures: or otp_app: discovery. (#148)
  • Discovery report and artifact identity drift: Chronicle.Client.discovery_report/1, identity_drift/1, a drift_policy: :ignore | :warn | :fail option (default :warn, never fails startup), a one-time warning for reactor, reducer and projection ids defaulted from the module name, and mix chronicle.discover. (#147)
  • Standalone constraint modules with use Chronicle.Events.Constraint, registered through constraints: or discovery, plus remove_constraint/2 with per-value removal properties, :scope and :event_sequences on unique_event_type, violation message callbacks, and Chronicle.Events.ConstraintViolation.details/1. (#143)
  • Projections: a one-line children form, removed_with_join/2, clear_with/2, a default :on for joins inside children, and compile-time errors for a root join without :on, a duplicate property target and an unknown field. (#127)
  • Read models: shared, self-reconnecting subscriptions with Chronicle.ReadModels.subscribe/2 and unsubscribe/1, :filter and :sort on observe/2, observe_stream/2, and Chronicle.Projections.query/2, preview/2 and wait_for/3. (#144)
  • ConcurrencyScope pipe helpers (with_sequence_number/2, with_event_types/2, with_event_stream_id/2 and more) and at_tail/2, and an opt-in client-wide concurrency: [default: :optimistic, check_first_append: true] strategy. (#134)
  • Prepared events with EventLog.prepare/2 and append_prepared/3, get_metadata_at/2, and initiator_type and resolved_caused_by in event metadata. (#150)
  • generation_for: on use Chronicle.Events.EventType declares a generation of another event type, and the strict_validation: true client 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 with event_generation_delivery:. (#119)
  • Chronicle.Patterns queries behavior patterns, including get_patterns_at/3 for a moment and time_bucket/1, which uses the same rule the engine mines with. (#39)
  • OpenTelemetry spans and :telemetry events for appends, reactors and reducers, and W3C trace context on every gRPC call, following the shared Cratis convention. The package now depends on opentelemetry_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_type constraints 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() or not_active() are now honored by Chronicle 19.33 and later. (#113)
  • watch/2 and observe/2 stop 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)