Best practice to query for Saga status?

Starting with common sample of the Shipping policy saga in the tutorials (don’t ship order unless OrderPlaced and OrderBilled are true) is there a suggested way to query for orders that have not met the policy yet?

Say a person calls in and says, “where’s my order?” If our policy is wrapped up in the saga logic, how could I query for that state of that policy in a proper manner. I’ve read that querying the saga data direclty isn’t really a good practice. Is the only solution to save some type of status in the order itself and have the saga fire off additional messages to update that status as it progresses (while in this scenario that might be a great solution, it does seem almost like you’re just recreating a second location to store the saga state).

I’m curious in general about the idea of “querying” for saga state for several scenarios. I picked the simple ShipOrder saga as it’s a sample from NSB to help convey my thoughts.

Thanks.
Stephen

In general you should not query the saga store. The schema isn’t optimized for it.

Your pattern to publish an event to indicate a certain state is very common. A subscriber can decide to store that for its UI to show. In your case very specific to your query requirement “orders that have not yet shipped”. Another component could in isolation become fully responsible in tracking and communication/visualizing this.

Another common pattern is to have a Handler on the same message that stores data in a view model.

For example:

class MySaga : Saga<MyState>, IHandleMessages<MyMessage>
{
    public async Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        // Only store 2 properties required for this policy
    }
}

class MyHandlerThatUpdatesAViewModel, IHandleMessages<MyMessage>
{
    public async Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        // Store all data for viewing purposes
    }
}

That separates the concerns as well. You could even have multiple different view models that store different things or for different reasons (for example, full-text search).

Your second query “Get order” is a very different query similarly as querying for an order its shipping status.

Keep in mind that often sagas are only orchestrators that make decisions based on a subset of data from their stored and incoming state.

You could have another component that blindly adds everything into a single viewmodel that stores everything in a single table (like the secondary handler example) wilth lots of nullable columns and be eventually consistent with the processes that each have ownership on their snippets of data required for their.

Last is very common often state can be assumed based on the fact that certain data doesn’t exist yet. For example, order isn’t known to be shipped because shipping info regarding the parcel could not be queried. Very often this is only a user-interface concern. If this is important for some business process often you want to track that based on business event that is defined in the process.

can we not send a message to the saga and have it reply with the all the saga data (State), through which we can infer the status of the order ? i

just curious, is this a bad practice ?

@ramonsmits when you get a moment, can you comment on my previous reply ?,