Repository navigation
Release v22.10.5
Summary
Cratis.Chronicle, Cratis.Chronicle.AspNetCore and Cratis.Chronicle.Testing are updated from 16.39.1 to 17.0.4, picking up 16.39.2, 16.40.0, 16.41.0, 16.42.0, 16.42.1, 16.42.2, 16.43.0, 16.44.0, 16.44.1, 16.44.2, 16.45.0, 16.45.1, 16.45.2, 16.45.3, 17.0.1, 17.0.2, 17.0.3 and 17.0.4.
Added
- Chronicle 16.40.0:
ChronicleOptions.RegistrationRetry— registering a client's artifacts is now retried with an exponential backoff instead of failing host startup when the Kernel is busy. Five attempts by default, 2s growing to 30s, all configurable (Cratis/Chronicle#3869) - Chronicle 16.40.0: Failed partition attempts carry what kind of failure they were —
Handling,Timeout,DisconnectedorUnknown— surfaced through the client SDK and the Workbench API (Cratis/Chronicle#3869) - Chronicle 16.41.0: Behavior pattern mining across every event flowing through an event store, using a bounded streaming sketch so storage scales with distinct recurring behavior rather than event volume (Cratis/Chronicle#3857)
- Chronicle 16.41.0:
IPatterns.GetPatternsAton the .NET client — a scope plus an optional moment defaulting to now, with the day and the part of the day derived using the same rule the engine bucketed events with when it mined them.GetPatternsremains underneath for a context that is not a moment. - Chronicle 16.41.0:
ToTimeBucket()onDateTimeOffset, the engine's own bucketing rule, so an application asking about a moment does not have to carry a second copy of it — a copy that would drift silently, returning nothing rather than failing - Chronicle 16.41.0:
IPatterns.GetScopeson the .NET client and thePatternsgRPC service, listing the scopes that hold established patterns — what a browsing surface needs before it can offer one - Chronicle 16.41.0: Behavior patterns in the Workbench: a pivot over everything established, across scope, command, initiator, day, time of day, aggregate, cause and specificity, with a confidence bar on each card
- Chronicle 16.41.0: Pattern heatmap in the Workbench: a day-by-time-of-day grid shaded by activity on a perceptual color scale, with a panel naming what a scope usually does at a given moment
- Chronicle 16.41.0: Backoffice sample generating half a year of backdated internal business activity — accounts payable, the ledger, procurement, HR and payroll — where everybody holds three or four different jobs at different points in the week, and one actor deliberately has no routine at all
- Chronicle 16.42.0:
GetUsualActionson the .NET client and thePatternsgRPC service — given a situation, what is usually done in it, ranked by confidence and at most one answer per action (Cratis/Chronicle#3872) - Chronicle 16.42.0:
FacetName.IsAction,FacetSet.WithoutActions()andBehaviorPattern.AnswersFor— the split between the action a pattern names and the context it was taken in, which mining already relied on privately - Chronicle 16.42.1:
PatternDetection.PersistenceIntervalsetting controlling how often mined behavior patterns are persisted (default 5 seconds). - Chronicle 16.43.0:
MapValuesonEventTypeMigration<TUpgrade, TPrevious>— declare which value in one generation is which value in the other, once, and Chronicle applies the map forward when upcasting and inverted when downcasting. Values the map does not mention are carried across unchanged. - Chronicle 16.43.0:
MapValueson the migration property builder, for a translation that applies to one direction only. A direction that declares its own transformation for a property keeps it, overriding what the value map derives. - Chronicle 16.44.0: Time Scrubber, on both the Projections and Read Models views: step a read model instance through its history one event at a time, with the state after each event and a hover describing the event and its properties.
- Chronicle 16.44.0: Snapshots of a read model instance can be asked for per event instead of per correlation, through a new
Groupingon the snapshot request. It defaults to grouping by correlation, so existing callers are unaffected. - Chronicle 16.44.0: A projection can be generated as client code in TypeScript, Kotlin and Elixir alongside C#, selectable in the Workbench's generated-code panel. Languages whose client has no API for a given projection style are offered only for the styles they support.
- Chronicle 16.44.0:
ILanguageService.GetLanguagesSupportingreports which languages can generate a given projection style. - Chronicle 16.45.0: ASP.NET Core health check for the client connection, registered automatically by
AddCratisChronicleunder the namechroniclewith thechronicleandreadytags.AddChronicleHealthCheck(HealthStatus)registers it explicitly and chooses the failure status (Cratis/Chronicle#3943) - Chronicle 16.45.0:
CHR0051reports a reducer method that declares its current read model as non-nullable (Cratis/Chronicle#3947) - Chronicle 16.45.0: Documentation for the
[Index]attribute, covering why the declaration lives on the read model and how it survives a replay (Cratis/Chronicle#3942) - Chronicle 16.45.0: Documentation for the client health check (Cratis/Chronicle#3943)
- Chronicle 16.45.2: Documentation for addressing a nested property in a migration, and for the case that needs no property operations at all — adding or removing an optional property at any depth, where the target generation's schema drives both the filling and the dropping (Cratis/Chronicle#3949)
- Chronicle 17.0.1: gRPC wire compatibility gate that runs before anything else builds, checking the contract at HEAD against every released minor of the current major and reporting each one. A major with no declared floor is compared in full. (Cratis/Chronicle#3873)
- Chronicle 17.0.1:
CheckCompatibilityon the connection service, so the kernel performs the one compatibility check for every client language instead of each SDK reimplementing it. A refused connection names the client version, the protocol version and the server version. - Chronicle 17.0.1: The canonical descriptor set now ships inside the .NET, Kotlin, TypeScript and Elixir contracts packages, so a client hands the kernel exactly what it was built against.
- Chronicle 17.0.1:
ProtocolVersionon the contracts, andServerVersionInfo.ProtocolVersionon the server. - Chronicle 17.0.1:
AllPatternsandAllPatternScopesqueries, so a namespace's behavior patterns can be browsed without choosing a scope first. (Cratis/Chronicle#3857) - Chronicle 17.0.1: Cross-cutting existence checks for event store, application and user: a command carrying one of those concepts is rejected when the thing it names does not exist, with no per-command wiring. A command that creates the entity opts its own property out.
Changed
Cratis.Chronicle,Cratis.Chronicle.AspNetCoreandCratis.Chronicle.Testingare updated to17.0.4- Chronicle 16.39.2:
Cratis.Arcupdated to 22.6.0. Events appended through an Arc command now carry the command that produced them, and a command executed from another command carries the one above it. - Chronicle 16.39.2: Every
[Command]declares a public instanceHandle()rather than an internal one, which is the contract Arc documents and now enforces. - Chronicle 16.40.0: When several methods on a reactor or reducer match the same event type, the public one now wins, then the one with the richest signature. A private helper extracted from a handler can no longer take that handler's place (Cratis/Chronicle#3870)
- Chronicle 16.40.0: A projection catches up through a single job step walking the sequence in global order, rather than one step per event source (Cratis/Chronicle#3869)
- Chronicle 16.40.0: Catch-up and replay bring their job steps up after subscribing has returned, so registering a projection no longer waits for them (Cratis/Chronicle#3869)
- Chronicle 16.40.0:
Observers.SubscriberTimeoutis now applied to subscriber calls — it previously had no effect at all. The default is raised from 5 to 30 seconds to match the bound the transport already imposes, so nothing changes for anyone who has not set it, and0now means waiting indefinitely rather than falling back to five seconds (Cratis/Chronicle#3869) - Chronicle 16.40.0: A partition whose last attempt timed out no longer counts toward the observer quarantine thresholds, so a congested period cannot take an otherwise healthy observer out of service (Cratis/Chronicle#3869)
- Chronicle 16.42.0:
GetPatternsAtanswers with commands rather than with the moment it was handed. It is built onGetUsualActionsnow, which is what its name and its documentation already promised. - Chronicle 16.42.0:
GetPatternsis unchanged and stays the call for the opposite question — given a situation you can describe completely, including the command, which established patterns cover it. That is the check to make before flagging an action as unusual, and it is the only one of the two answerable from a keyed candidate lookup. - Chronicle 16.42.2: The pattern miner is a per-event-store-and-namespace grain owning the mining lifecycle — sketches, restore of established patterns, and deferred persistence — with the capture subscriber reduced to extracting features and forwarding each observed batch as a single call to its store's miner.
- Chronicle 16.43.0: An event type generation whose enum only gained members, or had members renamed, no longer registers as
EventTypeSchemaChanged. The wider member list replaces the registered schema instead. Removing or renumbering a member is still a schema change that needs a new generation. - Chronicle 16.44.0: The Workbench is built on
@cratis/components4 and imports from explicit subpaths; Workbench-local components that the library now provides have been removed. - Chronicle 16.44.0: Projection code generation is now a seam with one generator per language.
DeclarativeCodeGeneratorandModelBoundCodeGeneratormoved intoCratis.Chronicle.Projections.Engine.DeclarationLanguage.CodeGeneration.CSharp, andLanguageServicetakes the discoveredIInstancesOf<IProjectionCodeGenerator>rather than the two C# generators directly — code that constructs these types itself, rather than resolving them, needs updating. - Chronicle 16.44.0:
ILanguageService.GenerateDeclarativeCodeandGenerateModelBoundCodetake the language to generate for, defaulting to C#, so existing calls are unchanged. - Chronicle 16.44.0: Generated C# declarative projections and model-bound records are formatted over multiple lines rather than one long line.
- Chronicle 16.44.0: The Backoffice sample correlates each generated command separately, so a generated history no longer looks like a single action.
- Chronicle 16.45.0: A client call made while the connection is down now fails instead of blocking its thread. A connect timeout surfaces as
ConnectionTimedOut, acquiring the connect lock is bounded by the connect timeout, and a failed attempt starts a back-off during which calls fail immediately withConnectionUnavailable. The watchdog still reconnects in the background, so a kernel that comes back is reachable again without restarting the client (Cratis/Chronicle#3948) - Chronicle 16.45.0: A reducer method whose current read model parameter is non-nullable is now rejected at registration rather than silently excluded from dispatch. The current read model is null for the event that creates an instance, so the declaration can only ever be a mistake. Methods in a
#nullable disablecontext are unaffected (Cratis/Chronicle#3947) - Chronicle 16.45.0: An ASP.NET Core host no longer fails to start when the kernel is briefly unreachable; the connection failure is logged and the health check reports it until the connection comes up (Cratis/Chronicle#3943)
- Chronicle 16.45.2: The JSON Schema
titleis no longer part of the schema comparison that guardsEventTypeSchemaChanged. It carries the CLR record name, so comparing it made renaming a record a breaking change despite a pinned[EventType("...")]identifier and an unchanged property set. It stays in the stored schema for tooling (Cratis/Chronicle#3926) - Chronicle 16.45.2: An event type migration can now address a property inside a nested object —
pb.DefaultValue(m => m.Price.Description, "unspecified")writes where it belongs, andpb.RenamedFrom(m => m.Price.Amount, e => e.Amount)moves a top-level value into the object it now belongs to. Registration validates such a path segment by segment and rejects one that resolves nowhere (Cratis/Chronicle#3949) - Chronicle 16.45.2: A
DefaultValuewhose target the generation's schema does not declare is now rejected at registration instead of skipped. Validation still exempts a default when the target generation has no schema to resolve against (Cratis/Chronicle#3949) - Chronicle 17.0.1: Every gRPC service is now derived from Arc
[Command]/[ReadModel]artifacts in Core rather than hand-written, completing the migration Cratis/Chronicle#2908 started.Source/Clients/ApiandSource/Kernel/Core/Servicesare gone; onlyObserversand the streaming services, whose server-to-client lifetime no command or query describes, remain hand-written. - Chronicle 17.0.1: Patterns is served by artifacts like everything else. Its five queries —
MatchingPatterns,UsualActions,PatternsForScope,AllPatterns,AllPatternScopes— read storage and the mining engine directly, and the contract is generated from them. (Cratis/Chronicle#3857) - Chronicle 17.0.1: Query parameters that name a concept are declared as that concept rather than as
string, so the value is validated on the way in instead of being cast inside the method. The wire is unchanged — a concept still travels as its primitive. - Chronicle 17.0.1: The two event-sequence lookups that answered with a bare
boolandulongnow answer withEventSourceEventsandEventSequenceTail. The value travels as the same primitive, one level in. - Chronicle 17.0.1: The Workbench's surfaces are served by Arc artifacts in the kernel, with proxies generated beside the features that use them rather than into a separate
Apifolder.
Fixed
- Chronicle 16.40.0: Adding a projection to an event store with a large event log could take the application down. Registration awaited one job-step grain being created, prepared and started per event source, exceeded its response timeout, failed host startup, and the restart re-registered into the queue it was waiting on (Cratis/Chronicle#3869)
- Chronicle 16.40.0: A reactor's handler was silently never invoked when the reactor also had a private helper whose first parameter was the same event type. Nothing was thrown and nothing was logged; only the missing side effects showed it (Cratis/Chronicle#3870)
- Chronicle 16.41.0: A constraint registered while its event sequence was already active was ignored for up to a second afterwards, so appends landing in that window bypassed it silently. The sequence now re-reads constraints on its first append after activation. This reaches any application that appends immediately after registering a constraint, not only the observer case it was found through. (Cratis/Chronicle#3868)
- Chronicle 16.41.0: Pattern capture subscribed only at server startup, so an event store whose clients connected afterwards mined nothing at all until the next restart. Capture now also subscribes when event types are registered. (Cratis/Chronicle#3867)
- Chronicle 16.41.0:
CHR0024reported a read-model mapping written as[property: SetFrom<T>]as having no mapping source. Both that spelling and the bare attribute on the parameter are honored at runtime; the analyzer read only the parameter. - Chronicle 16.41.0: The Workbench pattern scope selector showed its placeholder instead of the selected scope, while the views below it were already showing that scope's patterns.
- Chronicle 16.42.1: Bulk event ingestion no longer overwhelms pattern capture: observing only mines in memory, and the scopes an interval touched are persisted on a cadence — eliminating the subscriber timeouts, failed partitions, and retry-job storms high-rate appends previously caused.
- Chronicle 16.42.1: Behavior patterns are isolated per event store and per namespace — the same scope name in two stores, or in two tenants' namespaces, no longer counts into one sketch and contaminates both sides' persisted patterns.
- Chronicle 16.42.1: Established behavior patterns survive a server restart: a scope's persisted patterns are restored into the miner before its first event after a restart is mined, instead of being wiped in favor of whatever happened to occur first.
- Chronicle 16.42.1: A namespace added while the server is running is subscribed for pattern capture immediately, instead of only after the next restart or event type registration.
- Chronicle 16.42.1: The Backoffice sample's
generateis genuinely re-runnable: its history marker now lands on a well-known event source so the guarding uniqueness constraint actually turns a second run away. - Chronicle 16.42.2:
FacetSetnow round-trips System.Text.Json — its deserialization constructor previously could not bind, so any behavior pattern crossing a serialization boundary threw. - Chronicle 16.44.0: The Time Machine found no snapshots for a read model instance whose projection is keyed by a property rather than the event source.
- Chronicle 16.44.0: A projection preview returned instances without their key, so opening one in the Time Machine had nothing to look up.
- Chronicle 16.44.0: The pivot viewer clipped tile titles, lost pinch-to-zoom on trackpads and touch devices, and could leave tiles unreachable after zooming in grouped mode.
- Chronicle 16.44.0: Selecting a read model instance did not stick, which left the Time Machine disabled; selecting an event in the sequence editor showed no details.
- Chronicle 16.44.0: A details pane no longer cramps the columns of the grid beside it.
- Chronicle 16.44.0: Disabled buttons are visibly disabled, and the projection editor's help and source buttons stay inside the editor.
- Chronicle 16.44.0: Event store cards on the landing page are clickable as a whole, with the icon and title centered.
- Chronicle 16.44.0: A projection preview shows that it is running rather than appearing to hang.
- Chronicle 16.44.1: Event details in Sequences now shows the causation entry's own properties when navigating Context → causation → properties, instead of falling back to the root event context
- Chronicle 16.44.1: Navigating into the second or later causation entry now shows that entry's properties rather than the first entry's
- Chronicle 16.44.1: The property navigation breadcrumb shows which array element was navigated through, as
[0] - Chronicle 16.44.2: Stopped a shutdown requested during kernel startup from crashing with an unhandled exception; it now stops gracefully and logs the shutdown (Cratis/Chronicle#3936)
- Chronicle 16.44.2: Fixed a
NullReferenceExceptionwhen an observer activates against an unset projection definition (Cratis/Chronicle#3934) - Chronicle 16.44.2:
ReactorScenarionow surfaces what a reactor handler throws instead of swallowing the exception, so throwing reactors can be specced (Cratis/Chronicle#3933) - Chronicle 16.44.2: In-memory event sequence storage now records the real identity that caused an event instead of hardcoding
Identity.System, so in-process scenarios can assert event attribution (Cratis/Chronicle#3928) - Chronicle 16.44.2:
ReadModelScenario'sGetInstanceByIdnow returnsnullfor an instance that was never seeded instead of throwing (Cratis/Chronicle#3927) - Chronicle 16.44.2: The client now keeps retrying artifact registration in the background after it fails on an otherwise healthy connection, instead of leaving observers disconnected indefinitely until the next reconnect (Cratis/Chronicle#3935)
- Chronicle 16.45.0:
[AddFrom<T>]on a property of a[ChildrenFrom<T>]child no longer double-counts the event that creates the child entry. Accumulating child breakdowns produced exactly twice the value on the creating event, and every later event accumulated on top of that (Cratis/Chronicle#3940) - Chronicle 16.45.0: A job left persisted as running with all of its steps already completed is now finalized instead of reported as already running. Such a job stayed wedged forever and its observer could never resubscribe, leaving reactors disconnected indefinitely (Cratis/Chronicle#3944)
- Chronicle 16.45.0: A read model's declared indexes are now recreated on the collection a replay fills, so they survive the swap that ends the replay instead of being absent until the sink is rebuilt (Cratis/Chronicle#3942)
- Chronicle 16.45.1:
[Index]on a record's positional constructor parameter now declares an index, as the documentation says it does. Previously only[property: Index]worked, and the difference was invisible — nothing reported that a declaration had produced no index. (Cratis/Chronicle#3954) - Chronicle 16.45.2: A migration built from a nested property expression no longer fails registration with
InvalidMigrationPropertyForEventTypenaming a property that exists one level down (Cratis/Chronicle#3949) - Chronicle 16.45.2: A
DefaultValuetargeting a nested property no longer writes a top-level key with a dot in its name that the target generation's schema then discards, leaving old events upcasting with the value missing and no error anywhere (Cratis/Chronicle#3949) - Chronicle 16.45.3: Keyed model-bound child projections continue accepting updates after replay when an explicit event key matches the child key property. (Cratis/Chronicle#3922)
- Chronicle 17.0.1:
DateTimeOffsetreached the wire as an empty message, so ten fields — job creation times, user timestamps, event query date ranges — carried no value to Kotlin, TypeScript and Elixir clients. .NET was unaffected, which is why it went unseen. - Chronicle 17.0.1: The proto generator aborted for 22 of its 23 packages while exiting 0, so most generated contracts had silently stopped regenerating and an entire
SequenceQueriesservice had never been emitted at all. - Chronicle 17.0.1: Generated proto files and the descriptor set are now deleted and rewritten on every build, so a hand-applied edit to a generated file cannot survive.
- Chronicle 17.0.1:
AppendManywas silently dropping the caller-suppliedOccurredtimestamp for every event in the batch. - Chronicle 17.0.1: Pattern capture re-subscribes when registering event types introduces something new. A server starting against a store no client had connected to yet captured nothing at all until the next restart. (Cratis/Chronicle#3857)
- Chronicle 17.0.1: Failed-partition attempts carry their failure kind again, so a congestion timeout can be told apart from a subscriber that genuinely failed.
- Chronicle 17.0.1: An optional concept parameter generated an unguarded cast, so an absent value on the wire did not stay absent in the domain.
- Chronicle 17.0.2: Include
Cratis.Chronicle.Compatibility.dllin both Chronicle.Testing and Chronicle.XUnit.Integration so each package starts independently beside Arc (Cratis/Chronicle#3968). - Chronicle 17.0.3: Commands whose kernel-side handling depends on
IUnitOfWorkManager,IEventLog, orIEventTypes(any consumer combining Arc.Chronicle'sTransactionalCommandScope/*CommandResponseValueHandlertypes withCratis.Chronicle.Testing) failed to resolve inside the in-process kernel command pipeline used byEventScenario,EventStoreForTesting, andTestingServices- those interfaces fell back to auto-activating the real client implementations, which need a live connection the in-process kernel does not have. - Chronicle 17.0.4: Chronicle in-process tests no longer run consumer command execution scopes inside the kernel pipeline; avoids missing EventStoreName resolution and unintended nested consumer transactions. (Cratis/Chronicle#3973)