Release v15.40.0
Summary
This branch groups a set of related projection, reactor, and analyzer improvements developed across several parallel worktrees. The theme is surfacing silent model-bound projection and reactor mistakes at compile time — a new suite of Chronicle analyzers — alongside fixes to projection joins, reactor failure reporting, and the in-process ReadModelScenario test harness.
Added
New Chronicle analyzers:
- CHR0024 — model-bound read model property has no mapping source (no mapping attribute and no subscribed event carries a same-named property for AutoMap to bind).
- CHR0025 — a property set explicitly (e.g.
[SetFrom]) may be overwritten by AutoMap from another referenced event that carries an identically named property. Informational (not a warning), because the collision can be intentional; the message presents both resolutions (add[NoAutoMap], or accept the update). - CHR0026 —
[Key]/[Subject]placed on a property whose type derives fromEventSourceId<T>. - CHR0027 — a command both implements
ICanProvideEventStreamIdand carries a non-null[EventStreamId]. - CHR0028 — redundant
.AutoMap()call (already the default). - CHR0029 — redundant
.Set(x => x.P).To(e => e.P)with matching names. - CHR0030 — reactor invokes
ICommandPipeline.Executewithout[OnceOnly]. - CHR0031 — reactor declares mutable instance state.
- CHR0032 — reactor injects a storage primitive (e.g.
IMongoCollection<T>) directly. - CHR0033 — model-bound
[ChildrenFrom<E>]child collection property has no matching event property and no explicit mapping, so AutoMap fills it from nothing. - Code fixes for several of the above (remove
[Key]/[Subject], remove a redundant.AutoMap()/.Set().To()).
Other additions:
- A projection build-time warning when a collection read-model property auto-maps to nothing — the runtime companion to CHR0033, covering both model-bound and fluent projections.
- Model-bound projection value expressions now fail loud on unsupported accessors (method calls, arithmetic, conditionals, string interpolation, constants, or accessors that ignore the lambda parameter) instead of silently producing an empty or partial property path.
ReadModelScenariocan opt out of strict event subscription, so a seeded stream may carry events the read model does not subscribe to.
Fixed
- Model-bound join
Onproperty names are normalized to serialized naming, so a model-bound[Join]resolves consistently. - A
[Join]whose source event is keyed by a string concept (e.g. an organization number) no longer force-converts the key to a Guid-keyed read model's identifier and crash the projection — the read model materializes and stays spec-able (the joined value is enriched by the real engine). - Reactor side-effect append failures now report the target event source ids that failed to append.
[SetFromContext<E>]on a child parameter now honors its generic event type.