Skip to content

Release v19.58.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 13:51
8f99084

Summary

A read model can now fold its own events. Declare public static Reduce methods on the model that take the event and the current state and return the next state, and Chronicle runs them through the same reducer engine as IReducerFor<T>: registration, reconnect, passive reads, replay, generations, PII, external event stores and ReadModelScenario all behave the same. See Self-reducing read models.

Added

  • Self-reducing read models: a class that does not implement IReducer and declares public static Reduce(TEvent @event, TSelf? current[, EventContext context]) returning TSelf or Task<TSelf> is discovered as a reducer for itself. No marker attribute or new registration API is needed; [Reducer], [Passive], event-sequence, event-store, tag and route attributes on the model configure it, and the existing RegisterReducer<T>() and RegisterReducer(Type) accept these models. (#4731)
  • Optional static replay hooks on a self-reducing read model: BeginReplay, EndReplay, BeginReplayPartition(Partition) and EndReplayPartition(Partition) returning Task, with trailing services resolved from the notification's scope and no model instance created. (#4731)
  • Analyzers for self-reducing read models: CHR0058 warns about near-miss Reduce signatures, CHR0059 reports malformed replay hooks, CHR0060 reports equally specific Reduce methods, and CHR0061 reports a model that is also maintained by a projection or another reducer. (#4731)

Changed

  • Upgrade effect: an existing class that does not implement IReducer and already has a public static Reduce method of exactly that shape becomes a self reducer after upgrading. A static Reduce that only nearly matches logs a warning and is skipped; types implementing IReducer or IReducerFor<T> keep their current behavior. With Arc, mark such a model [ReadModel(RequireQueryAttribute = true)] and its query methods [Query] so Reduce is not exposed as a query endpoint. (#4731)

Fixed

  • Passive reducer reads now apply the reducer's tag, event source and stream filters, so on-demand state matches the state the active reducer builds. (#4785)
  • ReadModelScenario now applies reducer tag filters and keeps the tags, event source type and stream metadata of seeded events, so filtered reducers produce the same state in specifications as in production. (#4786)