MassTransit / Automatonymous

A state machine library for .Net - 100% code - No doodleware
Apache License 2.0
736 stars 117 forks source link

Catch in IfElse leads to Automatonymous.EventExecutionException #77

Closed qrogi closed 3 years ago

qrogi commented 3 years ago

Is this a bug report?

Yes

Can you also reproduce the problem with the latest version?

Yes

Environment

  1. Dotnet version: .NET 5.0
  2. Operating system: Windows 10 x64
  3. IDE (Rider, VS Code, Visual Studio): Rider

Steps to Reproduce

  1. Create MassTransitStateMachine with IfElse.
  2. In else clause create an activity that throws an exception.
  3. Catch that exception.

Expected Behavior

Catching in IfElse doesn't result in an exception.

Actual Behavior

After catching exception is thrown:

 ---> Automatonymous.EventExecutionException: The CreateModelRequested<CreateModelRequestedEvent> (Event) execution faulted
 ---> System.Exception: Exception of type 'System.Exception' was thrown.
   at WebApplication.ThrowExceptionActivity.Execute(BehaviorContext`2 context, Behavior`2 next) in C:\git\masstransit-ifelse-bug\WebApplication\Saga\ThrowExceptionActivity.cs:line 23
   at Automatonymous.Behaviors.ActivityBehavior`1.Automatonymous.Behavior<TInstance>.Execute[T](BehaviorContext`2 context)
   --- End of inner exception stack trace ---
   at Automatonymous.Behaviors.ExceptionBehavior`2.Automatonymous.Behavior<TInstance,TData>.Faulted[TException](BehaviorExceptionContext`3 context)
   at Automatonymous.Activities.ExceptionBehavior`3.Automatonymous.Behavior<TInstance>.Execute(BehaviorContext`1 context)
   at Automatonymous.Activities.TransitionActivity`1.Automatonymous.Activity<TInstance>.Execute(BehaviorContext`1 context, Behavior`1 next)
   at Automatonymous.Behaviors.ActivityBehavior`1.Automatonymous.Behavior<TInstance>.Execute[T](BehaviorContext`2 context)
   at Automatonymous.Activities.ConditionActivity`2.Automatonymous.Activity<TInstance>.Execute[T](BehaviorContext`2 context, Behavior`2 next)
   at Automatonymous.Activities.ActionActivity`2.Automatonymous.Activity<TInstance,TData>.Execute(BehaviorContext`2 context, Behavior`2 next)
   at Automatonymous.Behaviors.ActivityBehavior`1.Automatonymous.Behavior<TInstance>.Execute[T](BehaviorContext`2 context)
   --- End of inner exception stack trace ---
   at Automatonymous.Behaviors.ExceptionBehavior`2.Automatonymous.Behavior<TInstance,TData>.Faulted[TException](BehaviorExceptionContext`3 context)
   at Automatonymous.Activities.ConditionActivity`2.Automatonymous.Activity<TInstance>.Faulted[T,TException](BehaviorExceptionContext`3 context, Behavior`2 next)
   at Automatonymous.Behaviors.LastBehavior`1.Automatonymous.Behavior<TInstance>.Faulted[T,TException](BehaviorExceptionContext`3 context)
   at Automatonymous.Behaviors.DataBehavior`2.Automatonymous.Behavior<TInstance,TData>.Faulted[TException](BehaviorExceptionContext`3 context)
   at Automatonymous.Behaviors.ExceptionTypeCache.CachedConfigurator`1.Automatonymous.Behaviors.ExceptionTypeCache.CachedConfigurator.Faulted[TInstance,TData](Behavior`2 behavior, BehaviorContext`2 context, Exception exceptio
n)
   at Automatonymous.Behaviors.ExceptionTypeCache.Faulted[TInstance,TData](Behavior`2 behavior, BehaviorContext`2 context, Exception exception)
   at Automatonymous.Behaviors.ActivityBehavior`1.Automatonymous.Behavior<TInstance>.Execute[T](BehaviorContext`2 context)
   at Automatonymous.States.StateMachineState`1.Automatonymous.State<TInstance>.Raise[T](EventContext`2 context)
   at Automatonymous.States.StateMachineState`1.Automatonymous.State<TInstance>.Raise[T](EventContext`2 context)
   at Automatonymous.AutomatonymousStateMachine`1.Automatonymous.StateMachine<TInstance>.RaiseEvent[T](EventContext`2 context)
   at Automatonymous.Pipeline.StateMachineSagaMessageFilter`2.Send(SagaConsumeContext`2 context, IPipe`1 next)
   at Automatonymous.Pipeline.StateMachineSagaMessageFilter`2.Send(SagaConsumeContext`2 context, IPipe`1 next)
   at MassTransit.Saga.MissingSagaPipe`2.Send(SagaConsumeContext`2 context)
   at MassTransit.Saga.MissingSagaPipe`2.Send(SagaConsumeContext`2 context)
   at MassTransit.Saga.MissingSagaPipe`2.Send(SagaConsumeContext`2 context)
   at MassTransit.Saga.SendSagaPipe`2.Send(SagaRepositoryContext`2 context)
   at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.<>c__DisplayClass5_0`1.<<Send>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.<>c__DisplayClass8_0.<<WithinTransaction>g__Create|0>d.MoveNext()
--- End of stack trace from previous location ---
   at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.WithinTransaction[T](DbContext context, CancellationToken cancellationToken, Func`1 callback)
   at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.WithinTransaction[T](DbContext context, CancellationToken cancellationToken, Func`1 callback)
   at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.WithinTransaction[T](DbContext context, CancellationToken cancellationToken, Func`1 callback)
   at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.Send[T](ConsumeContext`1 context, IPipe`1 next)
   at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.Send[T](ConsumeContext`1 context, IPipe`1 next)
   at MassTransit.ExtensionsDependencyInjectionIntegration.ScopeProviders.DependencyInjectionSagaRepositoryContextFactory`1.<>c__DisplayClass6_0`1.<<Send>g__CreateScope|0>d.MoveNext()
--- End of stack trace from previous location ---
   at MassTransit.Saga.Pipeline.Filters.CorrelatedSagaFilter`2.GreenPipes.IFilter<MassTransit.ConsumeContext<TMessage>>.Send(ConsumeContext`1 context, IPipe`1 next)

Reproducible Demo

https://github.com/qrogi/masstransit-ifelse-bug A simple web API with get method, that initiating the saga through RabbitMQ. Persistence with PostgreSQL, don't forget to change connectionString.

phatboyg commented 3 years ago

Thanks, I've managed to reproduce this in the Automatonymous unit tests.

phatboyg commented 3 years ago

This is now in the latest develop packages for MassTransit. If you want to verify.

qrogi commented 3 years ago

It works, thank you!