rebus-org / Rebus

:bus: Simple and lean service bus implementation for .NET
https://mookid.dk/category/rebus
Other
2.3k stars 356 forks source link

Question about Sagas #888

Closed michaeldtaylor closed 4 years ago

michaeldtaylor commented 4 years ago

This isn't an issue as such (so feel free to close), but I'm trying to think through a solution, without over engineering it needlessly. I think I may be missing something simple, but I've read through the docs a few times and can't quite get my scenario.

I have some incoming queue messages (Azure Storage) that I poll for and:

await _bus.Publish(new BatchReceived
{
    BatchId = incomingBatch.BatchId
});

There is an IdempotentSaga in the same process that handles this message type and makes sure that the Batch gets processed into multiple database schemas. When every database schema has been updated, it marks the Batch as complete, and the Saga completes. All good.

Generally speaking there is only a single external message per day, so no issue. However, occasionally there might be a need for multiple.

The issue is that I only want the Saga to process a Batch at a time, in the order they were placed in the external queue. The process that holds the Saga has other handlers in it, so I can't just use:

o.SetNumberOfWorkers(1);
o.SetMaxParallelism(1);

Now I could just have some static application state, and only pop the external messages when that state said I could, thus serializing the BatchReceived messages in the correct order (and therefore only having a single Saga instance running at a time). However, is there any way to accept all the BatchReceived messages into the Azure Service Bus queue, but process them sequentially without setting SetNumberOfWorkers/SetMaxParallelism?

Just trying to think best practice here. Thanks for the advice!

mookid8000 commented 4 years ago

I think the easiest solution in your case would be to host your saga in a separate Rebus endpoint, with a separate input queue.

There's no problem with hosting themin the same process, so you can keep your units of deployment the same.

This way, you can serialize message processing in your saga's bus instance only.

In a way, it's also prettier that way, because the bus instance of your saga, and the bus instance that hosts your other handlers, seem to have different properties – that's often a sign that it would be beneficial to separate them.

Do you think that would work? 🙂

michaeldtaylor commented 4 years ago

It was something I'd considered, but wasn't sure if it was more "overkill". Sounds like a plan - thanks.