Question

We have two long running sagas that are both run for an infinite amount of time and respond to a timeout. The first subscribes to a timeout every 15 minutes, and the second every 24 hours. Each saga keeps track of its own execution time and notifies the other saga when it starts running and when it has completed. The bulk data loads these sagas are responsible for cannot be run at the same time due to database contention.

When the first saga (Saga A - 15 min) kicks off, it first checks (using an internal variable) to see if the second saga (Saga B - 24 hr) is currently running. If not, it begins its processing steps (shelling off to another process, and polling it over time to see when it's completed). These two sagas communicate through sending messages to notify each other when they're starting up or completed.

For some reason this seems smelly to me on two levels:

  1. We've essentially got a singleton saga that never completes. Is this an anti-pattern in its own right?
  2. We're sending messages bidirectionally with the sole intention of modifying state. It seems as though there should be a better way to handle this type of scenario. With the release of NSB 4.0, we started getting errors when sending commands. The errors cleared up when we used a pub-sub approach instead.

Is this considered an NServiceBus implementation anti-pattern, and is there a better pattern for this sort of requirement?

Was it helpful?

Solution

Generally speaking, I don't think sagas communicating with each other is an antipattern. In your specific case, however, it does sound smelly.

From what you've said about the behaviors, it appears as if this could be a single saga. A saga can request multiple timeouts of different types. So you could effectively merge these sagas, but then you'd be able to get rid of all the messages that exist just for the purpose of modifying state in the sibling, because the state would be shared.

In a general sense, however, it's perfectly fine for sagas to communicate. Doing so through commands should be treated carefully, as that creates direct coupling between the two, although this is still possible. An example would be a parent and child saga pair, where the parent workflow commands a child workflow to begin, but the child workflow is independent until it replies to its parent that it's done. We just realize that these are tightly coupled processes within the same service boundary. We might do this just to keep each saga more focused, or because the parent starts multiple child sagas with different data.

An even better example is saga communication through events. One saga will publish an event, and another saga will respond with its own long-running process. This is all decoupled and good. However if the second saga publishes an event that the first one responds to, then even though you're using events you've created a loop, so it's really not that dissimilar from commands at that point although it is still decoupled from any other external subscribers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top