Fix projection and reducer registration with Chronicle server#15
Merged
einari merged 9 commits intoMay 11, 2026
Merged
Conversation
The function was previously inlined in EventSequence.ts. Moving it to the connection module lets Reducers and Projections reuse it without duplicating the Guid-to-protobuf conversion logic.
Provides named Guid constants for the well-known Chronicle sink types so Projections and Reducers can reference them by name rather than embedding raw UUID strings.
When tsx/esbuild strips design:type metadata, mapRuntimeTypeToSchema
returns an empty object {}. Previously these empty schemas were included,
producing a required list that caused server-side Guid.Parse failures on
non-Guid event source IDs. Now any property with no resolved type is
omitted from both properties and required, and a model with zero resolved
properties emits an empty schema so the server falls back to accepting all
event content as-is.
…omEvent The separate @ModelBound decorator and ModelBoundProjection DecoratorType were redundant — any class decorated with @fromEvent and @readModel is by definition a model-bound projection. The discovery path now uses those existing decorators, removing the need for an extra annotation and the ModelBoundProjection entry from the type registry.
…tUpdated Three related fixes: - Wrap each projection registration in registerWithRetry() with up to 5 attempts and exponential back-off (2 s → 15 s cap). Addresses a race where Chronicle's Orleans grain returns UNKNOWN on a clean database when two projections register simultaneously. - Replace new Date().toISOString() with a deterministic djb2 hash over the sorted definition JSON. Previously every client restart produced a new timestamp, causing the server to treat every registration as a definition change and trigger a full replay. - Add optional readModelType parameter to @Projection() so declarative projections can declare their read model constructor explicitly when TypeScript generic inference is insufficient. - Add PropertyAccessor overload to setFromContext() for type-safe context property selection.
…ations Reducers were registering observations without first registering their read models with the kernel, causing the server to use a null/default sink instead of MongoDB. Added registerReadModels() called before startObservation() to declare each reducer's read model schema, sink type, and observer binding so Chronicle persists reducer state to MongoDB.
…ADME - Export WellKnownSinks from the package root index so consumers can reference sink identifiers without importing from internal paths. - Add debug-level log of raw event content in Reactors to aid diagnosing event dispatch issues. - Remove @modelBoundProjection from the decorator list in README; it has been replaced by @fromEvent.
…ixed events - Assign predefined Guid strings as event source IDs for seeded employees so projections using id: Guid on the read model parse correctly. - Add address, city, zipCode, country fields to all four event types and the EmployeeState read model. - Expand EmployeeStateReducer from interface to @readModel class with full address fields and an employeeAddressSet handler. - Add employeeAddressSet handler to HrNotificationReactor. - Fix employeeMoved to use event.city / event.country rather than the stale event.newCity field. - Extend projections (declarative and model-bound) to project address fields from EmployeeAddressSet and EmployeeMoved events.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixed
new Date()for theLastUpdatedfield.UNKNOWN/UNAVAILABLEgRPC error on clean databases (Orleans grain contention race).JsonSchemaGeneratorno longer emits empty property schemas when tsx/esbuild stripsdesign:typemetadata; properties with unresolvable types are omitted and the server's fallback path is used instead.@modelBounddecorator removed; model-bound projections are now discovered automatically from classes decorated with@fromEventand@readModel, eliminating a redundant annotation.toContractsGuidmoved toconnection/Guid.tsso it is shared acrossEventSequences,Projections, andReducerswithout duplication.@projection()decorator accepts an optionalreadModelTypeconstructor parameter for cases where generic inference is insufficient.setFromContext()accepts aPropertyAccessor<EventContext>in addition to a plain string for type-safe context property selection.