Skip to content

CHR0056: Explicit routing contradicts a typed event source filter

[FromEventSource<TSource>("stream")] decides both filters of a reactor or reducer: the event source type is the definition’s name, and the event stream type is the stream name. If the same type also carries [EventSourceType] or [EventStreamType], the explicit value may only repeat what the typed filter implies. A different value contradicts it.

CHR0056 reports each contradicting attribute on its own line. The rule is checked only when the stream exists. If the stream is undeclared, CHR0055 reports it instead.

Error

using Cratis.Chronicle.Events;
using Cratis.Chronicle.EventSources;
using Cratis.Chronicle.Reactors;
[EventType]
public record Chr0056PaymentReceived(decimal Amount);
[EventSource("orders")]
[EventStream("placement")]
public class Chr0056OrderEventSource : IEventSource;
// Error CHR0056 twice: both attributes contradict the typed filter, which already means
// event source type "orders" and event stream type "placement".
[FromEventSource<Chr0056OrderEventSource>("placement")]
[EventSourceType("invoices")]
[EventStreamType("payment")]
public class Chr0056PaymentReactor : IReactor
{
public Task Received(Chr0056PaymentReceived @event, EventContext context) => Task.CompletedTask;
}

View C# snippet source on GitHub

Remove the [EventSourceType] and [EventStreamType] attributes. The typed filter says the same thing, and it is the one that is checked against the definition.

using Cratis.Chronicle.Events;
using Cratis.Chronicle.EventSources;
using Cratis.Chronicle.Reactors;
[EventType]
public record Chr0056FixPaymentReceived(decimal Amount);
[EventSource("orders")]
[EventStream("placement")]
public class Chr0056FixOrderEventSource : IEventSource;
// The typed filter alone says everything. Drop the string attributes.
[FromEventSource<Chr0056FixOrderEventSource>("placement")]
public class Chr0056FixPaymentReactor : IReactor
{
public Task Received(Chr0056FixPaymentReceived @event, EventContext context) => Task.CompletedTask;
}

View C# snippet source on GitHub

If you really need to filter on a different event source type or stream type, drop [FromEventSource<TSource>] and use the two string attributes alone. See Migrate from string routing.

Two filters that disagree can never both match, so the observer would not receive any event, and nothing would say why. The rule reports the disagreement at the attribute that causes it.