1

I am trying to find help on designing a Saga in NServiceBus 5.x that is started by 2 or more messages. This means that the saga will not start with a single message, but all messages must be present before the saga starts.

I don't quite understand how that would work, and there are no samples or examples to be found anywhere.

I read a couple of books that clearly state it's perfectly fine to have a saga started by several messages.

What I don't get is how the saga is found when you need e.g. 3 messages to start the saga. All 3 messages have to arrive, in any order, before the saga can "start". How does this affect my choice of the [Unique] attribute?

Example: I need saga that is "unique"ly identified by three IDs "StoreID", "ComputerID", "UserID". Those three IDs would arrive in three distinct commands, Message1, Message2, Message3.

public class MySaga : Saga<MySagaData>, 
IAmStartedByMessages<Message1>, 
IAmStartedByMessages<Message2>, 
IAmStartedByMessages<Message3>
{ ...
}

Should MySagaData have the [Unique] attribute on three properties?

public class MySagaData
{
    [Unique]
    public int StoreId {get;set;}
    [Unique]
    public int ComputerId {get;set;}
    [Unique]
    public int UserId {get;set;}
}

Or do I have to create readonly property concatenating those three?

When Message1 and Message3 arrive, the saga can't be started. Message2 is missing.

Then another Message1 arrives.

Then Message2 arrives. (completing the first saga, so it can be started)

What about the second Message1?

How would this be handled?

tom redfern
  • 30,562
  • 14
  • 91
  • 126
John
  • 3,591
  • 8
  • 44
  • 72

3 Answers3

3

Every message handled by your Saga implementation received will belong to only 1 instance of that Saga. You will still need some way in each of those 3 messages to correlate them to the same Saga instance.

I would re-look at your process and see what it is that binds any three combinations of those 3 entities together to find what uniquely identifies the Saga, e.g. Order.

After this your Saga can just wait until it receives all 3 messages to start doing whatever it is you want to do by checking that all three of those IDs are set before doing whatever it is the Saga needs to do.

Bob.Langley
  • 336
  • 1
  • 5
2

Sagas do not support the pattern you are describing. IAmStartedByMessages directives are applied with an ANY, rather than ALL, semantic.

Broadly, you have two options;

  1. Start your saga instance with one of the required messages and then just handle the arrival of the others as and when they are sent, or
  2. Implement either the Aggregator or Observer pattern at some point before your saga is called, which will obviously remove the requirement to wait for multiple messages.
Jim G.
  • 15,141
  • 22
  • 103
  • 166
tom redfern
  • 30,562
  • 14
  • 91
  • 126
  • thanks Tom. Both options are viable, however what I have done now is to start saga 1 with the StoreID only. Then start Saga 2 from within Saga 1 with StoreID + ComputerID. Then start saga 3 from there using StoreID + ComputerID + UserID. It's somewhat a nesting of 3 sagas. So a message with StoreID + COmputerID in it, will find the Saga 2, not Saga 1 or 3. Is that a valid approach? – John Sep 20 '16 at 11:59
  • @John - it's very elegant. Difficult to predict if it will lead to any issues, but you can only try and find out. – tom redfern Sep 20 '16 at 15:08
0

It sounds to me like the act of starting the saga is a saga. What if you created a saga to manage the collection of the messages and then start a different one to do whatever work is pending the arrival of those messages.

Adam Fyles
  • 6,030
  • 1
  • 23
  • 29