Sagas can transition to their next state and consume messages before the previous NHibernate transaction has completed

27 views
Skip to first unread message

Mike Hadlow

unread,
Oct 22, 2009, 12:27:31 PM10/22/09
to masstransit-discuss
Sorry for the long title :p

I've been seeing messages arriving at a saga based service ignored
because the previous instance of the saga has not yet been saved to
the database.

OK, say I have a saga like this:

Initially(
When(NewNotifiableEvent)
.Then((workflow, message) => workflow.ProcessNewNotifiableEvent
(message))
.TransitionTo(WaitingForPdfCreation)
);

During(WaitingForPdfCreation,
When(PdfCreated)
.Then((workflow, message) => workflow.ProcessPdfCreated
(message))
.TransitionTo(WaitingForDocumentManagementInsertion)
);
..... etc ....

1. A NewNotifiableEvent arrives at the service
2. A new saga is created.
3. ProcessNewNotifiableEvent() is called and a 'PdfCreationRequest'
message is published
4. Before the NHibernate transaction that saves the new saga
completes, the PdfCreated message arrives.
5. The AbstractSagaRepository asks the
NHibernateSagaRepositoryForContainers to load the saga, but it hasn't
been created yet so zero sagas are returned from the query and the
message is ignored.

The effect is that messages are consumed off the queue, but then
nothing happens.

Any thoughts?

Mike

Chris Patterson

unread,
Oct 25, 2009, 10:35:44 AM10/25/09
to masstrans...@googlegroups.com
Are you using transactional queues? 

Because if I'm right, the message you are sending to create the PDF should not even be receivable until the overall transaction is committed.

If you are not using transactional queues, then you could likely have the behavior you are seeing.

I've got a local set of changes that I'm about to commit that have tests for everything you mention here.

The one thing that I have found that is a constant. If you have two external sources producing messages that would target the same saga, one that can initiate the saga, and one that is applied to an existing saga (both messages have a matching correlation pattern that would result in the same saga), if the initiating message has not been processed, the second message is not processed even after the first one gets processed. There is really no way around it other than to make both messages so they will create or use an existing saga, which will cause a duplicate key exception if they both try to create a new one at the same time. This will result in the message being retried up to 'n' times, which should allow it to apply itself to the saga now that it exists.

Once I've had some more testing time with the local changes, I'll put them into the trunk. Overall I think the behavior is more clearly specified.


Chris Patterson



Chris Patterson

unread,
Oct 25, 2009, 5:20:15 PM10/25/09
to masstrans...@googlegroups.com
I just committed the changes to make sagas and concurrency work more nicely together.

Make sure you're using transactional queues and this error of which you speak should no longer occur since the publish from the initially even handler won't be committed until the entire transaction is committed at the end of the message handler.


On Oct 22, 2009, at 11:27 AM, Mike Hadlow wrote:

Chris Patterson



Mike Hadlow

unread,
Oct 30, 2009, 11:06:02 AM10/30/09
to masstransit-discuss
Thanks Chris, Now I've got questions about configuring transactional
queues. Thought it was better as a new post though.
> chrisfromtu...@gmail.com
Reply all
Reply to author
Forward
0 new messages