Release v16.16.0
Caution
Known broken package — Cratis.Chronicle.Testing in this release bakes in Cratis.Screenplay 1.x types, so consumer specs fail against Screenplay 2.0+ (#3598). Use v16.19.3 or later.
Summary
Defects and missing seams found running Chronicle in a large production application.
Added
IEventStore.Registrationreports what became of each declared artifact when registration ran, and what stopped the run if it failed, withWaitForRegistration()to await itIProjections.GetStateForModel<TReadModel>()andGetFailedPartitionsForModel<TReadModel>()reach a projection by the read model it maintains, which for a model-bound projection is the only handle there isReadModelScenarioexposes the client artifacts registry, so a spec can ask which artifacts were registered[ReservedProtoFields]keeps retired proto field numbers reserved across regenerationCHR0039now covers every awaitable and the integration testing surface
Changed
- A unique constraint violation message no longer includes the offending value; it moved to the violation details, where the application chooses whether to render it
- Client
EventSequenceNumber.Maxis nowulong.MaxValue - 1, matching the kernel; code that captured the old value sees it as an ordinary sequence number - Subscribing the same handler to
IConnectionLifecycle.OnConnectedorOnDisconnectedtwice now subscribes it once; removing is unchanged IEventStoregains a member, so any implementation outside this repository must add it
Fixed
- The pre-16.12 constraint-store upgrade shipped but never ran, because its serializer was never registered
- One unregistered event type aborted projection discovery for every projection, taking the whole read side down
- A projection replay rewrote every stored child whole, defaulting every member the projection did not set
- Reading a read model turned an absent collection into
nullinstead of an empty one - The compliance release pass blanked a value that had never been encrypted
- A client concurrency scope meaning "no expected sequence number" arrived at the kernel as an ordinary number, so the kernel ran a check that could only pass
- A skipped concurrency check was attributed to the caller
GetStateFor<TProjection>()looked in the read model dictionary with a projection type, so it could only ever throw- A failed projection registration named every identifier in the batch instead of the definition that failed
- A registration that threw left its outcome looking unfinished, so a consumer waiting on it timed out instead of being told what failed
- Two projections maintaining the same read model resolved silently by declaration order
- Two dependency injection containers in one process sharing a namespace were handed the same event store
- Concurrent callers asking for the same event store each built their own and ran discovery twice
- An event store that could not be reached on its first resolution stayed unreachable for the lifetime of the process
CHR0002demanded[EventType]on generic arguments that are not eventsCHR0004andCHR0005analysed a reactor's private helper methods as if they were handlersCHR0010counted the absence of[EventStore]as a distinct store, so a single-store projection reported as multi-storeCHR0025reported a collision an event named by[ChildrenFrom]cannot cause- The code analysis rule index was missing its
CHR0039row [NoAutoMap]was ignored on[ChildrenFrom]children and[Nested]members, and a nested object used the root's exclusions instead of its own- Two
[SetFromContext<T>]for the same event type on one member silently discarded all but the last - A
message:on a property-level[Unique]was silently discarded - Three attribute docstrings promised that projections filter on event metadata
Cratis.Chronicle.XUnit.Integrationomitted the embedded kernel's runtime dependencies from its package- A unique constraint definition compared its covered events by reference, so every re-registration looked like a change and asked for a reindex