Subscribe Reducers to External Event Stores
Automatic Inbox Routing
Section titled “Automatic Inbox Routing”When all event types reduced by a reducer come from the same source event store, Chronicle routes the reducer to the matching inbox sequence automatically:
- Source event store:
fulfillment-service - Inbox sequence observed by the reducer:
inbox-fulfillment-service
This works when the source is declared on event types (or assembly) using [EventStore("...")], and no explicit event sequence is configured on the reducer.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Reducers;
[EventType][EventStore("fulfillment-service")]public record ExternalReducerShipmentDispatched(Guid OrderId, string TrackingNumber);
public record ExternalReducerFulfillmentStatus(string Status, string TrackingNumber);
public class ExternalReducerFulfillmentStatusReducer : IReducerFor<ExternalReducerFulfillmentStatus>{ public ExternalReducerFulfillmentStatus Dispatched(ExternalReducerShipmentDispatched @event, ExternalReducerFulfillmentStatus? current, EventContext context) => new("Dispatched", @event.TrackingNumber);}Observer-Level EventStore for Missing Event Metadata
Section titled “Observer-Level EventStore for Missing Event Metadata”When event contracts cannot carry [EventStore] metadata, apply [EventStore] directly on the reducer.
Chronicle resolves the reducer to the inbox for that source event store and implicitly creates or reuses the outbox-to-inbox subscription.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Reducers;
[EventType]public record ExternalReducerUserInvited(Guid UserId);
public record ExternalReducerUserTotals(int Count);
[EventStore("identity-service")][Reducer]public class ExternalReducerUserTotalsReducer : IReducerFor<ExternalReducerUserTotals>{ public ExternalReducerUserTotals Invited(ExternalReducerUserInvited @event, ExternalReducerUserTotals? current, EventContext context) => new((current?.Count ?? 0) + 1);}Implicit Combined Event Type Filtering
Section titled “Implicit Combined Event Type Filtering”For each source event store, Chronicle combines all reducer and reactor event types into one implicit subscription filter.
This means:
- You get one subscription per source event store.
- The filter is the union of handled event types from all participating observers.
- Only those event types are forwarded from source outbox to target inbox.
Explicit Event Sequence Is Not Allowed with Observer EventStore
Section titled “Explicit Event Sequence Is Not Allowed with Observer EventStore”When a reducer has [EventStore("...")], do not combine it with:
[EventSequence("...")][EventLog][Reducer(eventSequence: "...")]
This is invalid and fails:
- At runtime with
EventStoreCannotBeCombinedWithExplicitEventSequence. - At compile time with analyzer rule
CHR0014.