Skip to content

Inferred message identity for sagas needs to be able to infer from the saga-id header too #4484

Open

Description

@jeremydmiller
No description provided.

Activity

  1. jeremydmiller commented on Sep 18, 2026

    @jeremydmiller
    MemberAuthor

    Also account for Fault<T> messages in this case as well too.

  2. GeorgeF0 commented on Sep 22, 2026

    @GeorgeF0

    Hi Jeremy! Here's a little bit of write-up from our discussion the other day:

    Message partitioning for sagas allows us to use the scatter-gather style of work, particularly useful in batch processing, without paying the cost of concurrency-related retries.

    Currently, UseInferredMessageGrouping requires the saga ID to be explicitly provided in response messages, so that routing works correctly.

    This works fine if the handlers that send the responses belong to the same saga. This detail is contained within the saga "module" itself and the responsibility of the saga author to get right. However, if the handlers belong elsewhere (ex: domain logic handlers), then they need to become aware of the fact that they may participate in a saga, and places the burden on those handlers to remember to include the saga ID explicitly in their response - otherwise they break routing back in the saga.

    A saga-aware domain handler would look like this:

    public static (Events, OutgoingMessages) Handle(DoSomeDomainWork command)
    {
        // ... business logic that may emit events ...
    
        var messages = new OutgoingMessages();
        if (command.SagaId is { } sagaId /*alternatively check the Envelope*/) // only when the request came from a saga: separate issue/consideration/discussion, see note below
            messages.Add(new SomeDomainWorkCompleted(sagaId /* must remember to copy this explicitly */, /* extra info */));
    
        return (events, messages);
    }

    Where header-based saga ID inference really shines, however, is when it comes to fault events. The user cannot edit/customize fault events and never gets the chance to add a saga ID field in there. Deriving it from the header would fix this issue.

    Note on the conditional response message bit: even with the above fix, domain handlers will still need to be saga-aware, because cascading responses when not used by a saga will still trigger the saga handler of that response. Messages with no saga ID (whether header or property) throw with a IndeterminateSagaStateIdException. While domain handlers can optionally emit responses based on the presence of a saga ID, Fault events don't have that option. So a faulted domain handler used by a saga will cause the saga to throw if the fault happened while processing a message not sent to the handler by the saga. This could be solved with a IdNotProvided hook in a similar fashion to NotFound that gives the user the chance to handle such messages.

  3. modified the milestone: 7.0 on Sep 23, 2026
  4. jeremydmiller commented on Sep 29, 2026

    @jeremydmiller
    MemberAuthor

    @GeorgeF0 Hey, has your bunch thought anymore about a possible engagement around this and some of the other things we talked about the other week? I thought about trying to take this in for a "quick" release today and remembered that it's a little bit involved, so it's time to follow up with you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions