Saga shopping cart example and correlation

115 views
Skip to first unread message

Shukhrat Nekbaev

unread,
Jul 25, 2016, 9:15:31 AM7/25/16
to masstransit-discuss
Hi,

I'm pretty new to MT and trying to wrap my head around sagas and correlation.

Context is the shopping cart example. What is the difference between these two:

Event(() => ItemAdded, x => x.CorrelateBy(cart => cart.UserName, context => context.Message.UserName).SelectId(context => NewId.NextGuid()));
and
Event( () => ItemAdded, x => x.CorrelateById(  context => NewId.NextGuid() ) );

It seems to work both ways. Is the second version I came up with equal to the original one but just shorter?
Thank you!

Chris Patterson

unread,
Jul 25, 2016, 4:43:29 PM7/25/16
to masstrans...@googlegroups.com
The latter actually does not work as adding multiple items to the cart would create separate sagas for each item. Instead of a single saga for the member. 

__
Chris Patterson




--
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/11b176fa-fd7d-493f-8d91-782fd5873b4b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shukhrat Nekbaev

unread,
Aug 3, 2016, 7:12:54 PM8/3/16
to masstransit-discuss
Hi,

sorry for the late reply. 

You were right. Regarding the very same correlation question:

Continuing my journey and now I'm trying to make sagas concurrent, moreover, planning to have multiple processes consuming same saga endpoints. At the moment testing with a single saga process. Using the latest MT, Azure ServiceBus and MT's EF extension for saga persistence.

Shopping cart example is failing for me if receive endpoint configuration has concurrency setting > 1. I tried adding exponential retry policy, it helped a bit, but still, many were failing. I thought ok, UserName value is the same maybe that's the problem, let me try and pass a guid value instead. So passed a random guid in the UserName property for the ICartItemAdded. Saga's event handler remained the same:

x.CorrelateBy(cart => cart.UserName, context => context.Message.UserName).SelectId(context => NewId.NextGuid());
then I added x.InsertOnInitial = true

created 30 messages and ran the service, but it was still failing for some messages:
Value cannot be null. Parameter name: connection.

Stacktrace:
at System.Data.Entity.Utilities.Check.NotNull[T](T value, String parameterName)
at System.Data.Entity.Infrastructure.Interception.DbTransactionInterceptionContext.WithConnection(DbConnection connection)
at System.Data.Entity.Infrastructure.Interception.DbTransactionDispatcher.Rollback(DbTransaction transaction, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.EntityClient.EntityTransaction.Rollback()

Then I commented out retry policy and changed saga's event handler to
x.CorrelateById(context => Guid.Parse( context.Message.UserName));

and that helped.

Saga endpoint config:

cfg.ReceiveEndpoint(
host,
"shopping_cart_state",
e =>
{
e.PrefetchCount = 50;
//e.UseConcurrencyLimit( 30 );
e.MaxConcurrentCalls = 30;
e.StateMachineSaga( _machine, _repository.Value );
} );

Now I'm a bit lost. I'm passing a unique guid in UserName property, so it has to be something related to establishing the correlation, the syntax, why the original one is failing then, hmm. Any help is welcome :)

Also, is there a difference between:
e.UseConcurrencyLimit( 30 ); and e.MaxConcurrentCalls = 30;

I might be wrong, but it feels like latter makes the processing a bit faster (I'm writing into files for every event in the saga, latter seems to generate the output faster)

Moreover, is there a good recommendation for PrefetchCount and UseConcurrencyLimit(  ) and/or e.MaxConcurrentCalls values? Some rule like PrefetchCount is recommended to be twice the value of UseConcurrencyLimit(  ) and/or e.MaxConcurrentCalls or something like that?

Thank you!

On Monday, July 25, 2016 at 11:43:29 PM UTC+3, Chris Patterson wrote:
The latter actually does not work as adding multiple items to the cart would create separate sagas for each item. Instead of a single saga for the member. 

__
Chris Patterson




On Mon, Jul 25, 2016 at 6:15 AM -0700, "Shukhrat Nekbaev" <particl...@gmail.com> wrote:

Hi,

I'm pretty new to MT and trying to wrap my head around sagas and correlation.

Context is the shopping cart example. What is the difference between these two:

Event(() => ItemAdded, x => x.CorrelateBy(cart => cart.UserName, context => context.Message.UserName).SelectId(context => NewId.NextGuid()));
and
Event( () => ItemAdded, x => x.CorrelateById(  context => NewId.NextGuid() ) );

It seems to work both ways. Is the second version I came up with equal to the original one but just shorter?
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.

Shukhrat Nekbaev

unread,
Aug 3, 2016, 7:22:49 PM8/3/16
to masstransit-discuss
Also what I just noticed is that if I keep the:

x.CorrelateById(context => Guid.Parse( context.Message.UserName));

but remove the:

x.InsertOnInitial = true

it also fails, but error is different, it's about deadlocking:

Transaction (Process ID 63) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
...
Reply all
Reply to author
Forward
0 new messages