How are race conditions avoided in the saga implementation?

240 views
Skip to first unread message

Lyndon Rebroost

unread,
Sep 13, 2014, 2:52:42 AM9/13/14
to masstrans...@googlegroups.com
Hello,

Lets say we have a service bus listening for OrderCreated and OrderApproved events, with a saga subscription that instantiates the saga on OrderCreated, and activates something on OrderApproved.
The service bus has a concurrent consumer limit of 10.

If an order is both created and approved at the exact same time, and published onto a queue, the service bus will receive these two events almost at the same time.
Isn't there a risk that the saga repository haven't finished handling the OrderCreated event (and persisting the saga instance), before the OrderApproved is received? In order to handle the OrderApproved event, the saga needs to retrieve it's instance, which might not be available.

I can't reproduce this using MassTransit, so I'm just curious how it's being avoided.

Thank you

Chris Patterson

unread,
Sep 14, 2014, 11:33:56 AM9/14/14
to masstrans...@googlegroups.com
The saga repository is on SQL server, and the isolation level is set to serializable, so the concurrency between two saga rows is handled that way.

Serializable is used so that the second message to hit the database is blocked until the previous transaction is completed. This can create a bottle neck on newly created rows, but existing rows do not have range lock issues as frequently.

--
You received this message because you are subscribed to the Google Groups "masstransit-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-dis...@googlegroups.com.
To post to this group, send email to masstrans...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/masstransit-discuss/ae66df0f-5ec0-4b3c-8cc4-0f098fac5131%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Lyndon Rebroost

unread,
Sep 15, 2014, 4:09:24 AM9/15/14
to masstrans...@googlegroups.com
The range lock from the serializable isolation level makes sense.

Another thing I've been wondering about, is how to be sure that the saga is persisted before something else raises an event that requires the saga to be in the "next" state.
This can of course not always be guaranteed, but when activating an activity from the saga, for example by publishing a message using the Publish method, the handler of this message can raise a new event subscribed to by the same saga. If the saga isn't persisted before retrieving this newly published message, the repository won't find the saga, hence loosing the potential state change?



Den søndag den 14. september 2014 17.33.56 UTC+2 skrev Chris Patterson:
The saga repository is on SQL server, and the isolation level is set to serializable, so the concurrency between two saga rows is handled that way.

Serializable is used so that the second message to hit the database is blocked until the previous transaction is completed. This can create a bottle neck on newly created rows, but existing rows do not have range lock issues as frequently.
On Fri, Sep 12, 2014 at 11:52 PM, Lyndon Rebroost <lyndonr...@gmail.com> wrote:
Hello,

Lets say we have a service bus listening for OrderCreated and OrderApproved events, with a saga subscription that instantiates the saga on OrderCreated, and activates something on OrderApproved.
The service bus has a concurrent consumer limit of 10.

If an order is both created and approved at the exact same time, and published onto a queue, the service bus will receive these two events almost at the same time.
Isn't there a risk that the saga repository haven't finished handling the OrderCreated event (and persisting the saga instance), before the OrderApproved is received? In order to handle the OrderApproved event, the saga needs to retrieve it's instance, which might not be available.

I can't reproduce this using MassTransit, so I'm just curious how it's being avoided.

Thank you

--
You received this message because you are subscribed to the Google Groups "masstransit-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-discuss+unsub...@googlegroups.com.

Tommy Jakobsen

unread,
Sep 19, 2014, 3:00:24 AM9/19/14
to masstrans...@googlegroups.com
I'm a bit curious about this as well. We've had the saga problem, where the saga publishes message X, whose handler publishes another message Y. The saga listens for Y, but sometimes the saga isn't persisted after publishing X and before handling Y. One way to solve this is to retry handling Y, but I think a better solution is to persist the saga before publishing messages (from the Publish method on AutomatonymousStateMachine (MT extensions)).

What do you think, Chris?

Chris Patterson

unread,
Sep 19, 2014, 1:27:38 PM9/19/14
to masstrans...@googlegroups.com
That explicit item you mention is being handled a little more effectively in MT3, by holding the events until the persistence step.

But the range locks and serialization should block the event handlers that are saga-based from being executed. Also, the events should include sufficient information that there is no need to refer back to the saga for more information (if they are handled by non-saga event handlers).


To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-dis...@googlegroups.com.

To post to this group, send email to masstrans...@googlegroups.com.

Tommy Jakobsen

unread,
Sep 29, 2014, 2:50:57 AM9/29/14
to masstrans...@googlegroups.com
Sounds really great about MT3. Looking forward to it :-)


On Friday, September 19, 2014 7:27:38 PM UTC+2, Chris Patterson wrote:
That explicit item you mention is being handled a little more effectively in MT3, by holding the events until the persistence step.

But the range locks and serialization should block the event handlers that are saga-based from being executed. Also, the events should include sufficient information that there is no need to refer back to the saga for more information (if they are handled by non-saga event handlers).

On Fri, Sep 19, 2014 at 12:00 AM, Tommy Jakobsen <to...@holmjakobsen.dk> wrote:
I'm a bit curious about this as well. We've had the saga problem, where the saga publishes message X, whose handler publishes another message Y. The saga listens for Y, but sometimes the saga isn't persisted after publishing X and before handling Y. One way to solve this is to retry handling Y, but I think a better solution is to persist the saga before publishing messages (from the Publish method on AutomatonymousStateMachine (MT extensions)).

What do you think, Chris?


On Monday, September 15, 2014 10:09:24 AM UTC+2, Lyndon Rebroost wrote:
The range lock from the serializable isolation level makes sense.

Another thing I've been wondering about, is how to be sure that the saga is persisted before something else raises an event that requires the saga to be in the "next" state.
This can of course not always be guaranteed, but when activating an activity from the saga, for example by publishing a message using the Publish method, the handler of this message can raise a new event subscribed to by the same saga. If the saga isn't persisted before retrieving this newly published message, the repository won't find the saga, hence loosing the potential state change?



Den søndag den 14. september 2014 17.33.56 UTC+2 skrev Chris Patterson:
The saga repository is on SQL server, and the isolation level is set to serializable, so the concurrency between two saga rows is handled that way.

Serializable is used so that the second message to hit the database is blocked until the previous transaction is completed. This can create a bottle neck on newly created rows, but existing rows do not have range lock issues as frequently.
On Fri, Sep 12, 2014 at 11:52 PM, Lyndon Rebroost <lyndonr...@gmail.com> wrote:
Hello,

Lets say we have a service bus listening for OrderCreated and OrderApproved events, with a saga subscription that instantiates the saga on OrderCreated, and activates something on OrderApproved.
The service bus has a concurrent consumer limit of 10.

If an order is both created and approved at the exact same time, and published onto a queue, the service bus will receive these two events almost at the same time.
Isn't there a risk that the saga repository haven't finished handling the OrderCreated event (and persisting the saga instance), before the OrderApproved is received? In order to handle the OrderApproved event, the saga needs to retrieve it's instance, which might not be available.

I can't reproduce this using MassTransit, so I'm just curious how it's being avoided.

Thank you

--
You received this message because you are subscribed to the Google Groups "masstransit-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-discuss+unsubscribe...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "masstransit-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-discuss+unsub...@googlegroups.com.
To post to this group, send email to masstrans...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages