I have this simple process for my order process spanning multiple microservices.
Created > validated> Checkout session created > payed > collected. The result can fail at any step resulting in the "Cancelled" state.
I currently have the following as my state machine:
{
public Event<IOrderCreatedEvent> StartOrderProcess { get; private set; }
public Event<IOrderValidatedEvent> OrderValidated { get; private set; }
public Event<IOrderCheckoutSessionCreatedEvent> CheckoutSessionCreatedEvent { get; private set; }
public Event<IOrderPayedEvent> OrderPayed { get; private set; }
public Event<IOrderCollectedEvent> OrderCollected { get; private set; }
public Event<IOrderCancelledEvent> OrderCancelled { get; private set; }
public State Validated { get; private set; }
public State CheckoutSessionCreated { get; private set; }
public State Payed { get; private set; }
public State Collected { get; private set; }
public State Cancelled { get; private set; }
//Start => Validated => Session created => Payed => Collected
public OrderStateMachine()
{
InstanceState(s => s.CurrentState);
Event(() => StartOrderProcess, x => x.CorrelateById(m => m.Message.OrderId));
Event(() => OrderValidated, x => x.CorrelateById(m => m.Message.OrderId));
Event(() => CheckoutSessionCreatedEvent, x => x.CorrelateById(m => m.Message.OrderId));
Event(() => OrderPayed, x => x.CorrelateById(m => m.Message.OrderId));
Event(() => OrderCollected, x => x.CorrelateById(m => m.Message.OrderId));
Event(() => OrderCancelled, x => x.CorrelateById(m => m.Message.OrderId));
//Start
Initially(
When(StartOrderProcess)
.Then(context =>
{
context.Instance.OrderId = context.Data.OrderId;
context.Instance.PackagesId = context.Data.PackagesIds;
})
.Publish(context => new OrderValidatedEvent(context.Instance))
.TransitionTo(Validated)
);
//Validated => payment session created
During(Validated, When(
CheckoutSessionCreatedEvent).Then(context =>
{
context.Instance.OrderId = context.Data.OrderId;
context.Instance.PackagesId = context.Data.PackagesIds;
context.Instance.CheckoutSessionId = context.Data.SessionId;
})
.Publish(context => new OrderCheckoutSessionCreatedEvent(context.Instance))
.TransitionTo(CheckoutSessionCreated)
);
//Session created => payed
During(CheckoutSessionCreated, When(
OrderPayed).Then(context =>
{
context.Instance.OrderId = context.Data.OrderId;
context.Instance.PackagesId = context.Data.PackagesIds;
context.Instance.PaymentMethod = context.Data.PaymentMethod;
})
.Publish(context => new OrderPayedEvent(context.Instance))
.TransitionTo(Payed)
);
//payed => Collected
During(Payed, When(
OrderCollected).Then(context =>
{
context.Instance.OrderId = context.Data.OrderId;
context.Instance.PackagesId = context.Data.PackagesIds;
context.Instance.OrderCollectedDateTime = DateTime.Now;
})
.Publish(context => new OrderCollectedEvent(context.Instance))
.TransitionTo(Collected)
);
//Cancel order bij cancelled event
DuringAny(
When(OrderCancelled)
.Then(context =>
{
context.Instance.OrderCancelDateTime = DateTime.Now;
context.Instance.OrderId = context.Data.OrderId;
})
.Finalize());
SetCompletedWhenFinalized();
}
}
And this is the content of "OrderStateData"
public class OrderStateData : SagaStateMachineInstance
{
public Guid CorrelationId { get; set; }
public string CurrentState { get; set; }
public DateTime? OrderCreationDateTime { get; set; }
public DateTime? OrderCancelDateTime { get; set; }
public DateTime? OrderCollectedDateTime { get; set; }
public Guid OrderId { get; set; }
public List<Guid> PackagesId { get; set; }
public string CheckoutSessionId { get; set; }
public string PaymentMethod { get; set; }
}
However when I try to use this I get the following error
R-FAULT rabbitmq://localhost/Constants.OrderBus1 5f750000-61e0-00d8-0485-08d8c20620a5 MessagingContracts.Orders.IOrderValidatedEvent FS_Saga.OrderStateMachine.OrderStateData(00:00:00.1109663)
Automatonymous.NotAcceptedStateMachineException: FS_Saga.OrderStateMachine.OrderStateData(654b5d93-cb5a-4f58-a06c-3a25ac56532d) Saga exception on receipt of MessagingContracts.Orders.IOrderValidatedEvent: Not accepted in state Validated
---> Automatonymous.UnhandledEventException: The OrderValidated event is not handled during the Validated state for the OrderStateMachine state machine
at Automatonymous.AutomatonymousStateMachine`1.DefaultUnhandledEventCallback(UnhandledEventContext`1 context)
at Automatonymous.AutomatonymousStateMachine`1.UnhandledEvent(EventContext`1 context, State state)
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)
--- End of inner exception stack trace ---
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.SendSagaPipe`2.Send(SagaRepositoryContext`2 context)
at MassTransit.Saga.SendSagaPipe`2.Send(SagaRepositoryContext`2 context)
at MassTransit.Saga.InMemoryRepository.InMemorySagaRepositoryContextFactory`1.Send[T](ConsumeContext`1 context, IPipe`1 next)
at MassTransit.Saga.Pipeline.Filters.CorrelatedSagaFilter`2.GreenPipes.IFilter<MassTransit.ConsumeContext<TMessage>>.Send(ConsumeContext`1 context, IPipe`1 next)
I have a strong feeling my state machine is absolute garbage, but I cant find anything on how to set it up properly.
question from:
https://stackoverflow.com/questions/65903168/how-to-setup-a-masstransit-order-state-machine 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…