Untitled

mail@pastecode.io avatar
unknown
csharp
a month ago
4.0 kB
2
Indexable
Never
using System;
using MassTransit;

public class OrderSagaStateMachine : MassTransitStateMachine<OrderSagaState>
{
    public OrderSagaStateMachine()
    {
        Event(() => OrderPlaced, x => x.CorrelateById(context => context.Message.OrderId));
        Event(() => OrderPaid, x => x.CorrelateById(context => context.Message.OrderId));
        Event(() => OrderStartedShipping, x => x.CorrelateById(context => context.Message.OrderId));
        Event(() => OrderDelivered, x => x.CorrelateById(context => context.Message.OrderId));
        Event(() => OrderPaymentFailed, x => x.CorrelateById(context => context.Message.OrderId));
        Event(() => OrderShippingFailed, x => x.CorrelateById(context => context.Message.OrderId));
        Event(() => UserCancelledOrder, x => x.CorrelateById(context => context.Message.OrderId));

        Schedule(() => ExpirationTimeout, x => x.ExpirationTokenId, x => 
            x.Delay = TimeSpan.FromDays(7));

        Initially(
            When(OrderPlaced)
                .Then(context => 
                {
                    context.Saga.OrderDate = DateTime.UtcNow;
                    context.Saga.CurrentState = OrderState.Created;
                })
                .Schedule(ExpirationTimeout, 
                    context => new ExpirationTimeoutMessage { OrderId = context.Saga.CorrelationId })
                .TransitionTo(Created)
        );

        During(Created,
            When(OrderPaid)
                .Unschedule(ExpirationTimeout)
                .TransitionTo(Paid),
            When(ExpirationTimeout.Received)
                .TransitionTo(Cancelled)
                .Then(context => context.Saga.CancellationReason = "Order expired"),
            When(UserCancelledOrder)
                .TransitionTo(Cancelled)
                .Then(context => context.Saga.CancellationReason = "Cancelled by user")
        );

        During(Paid,
            When(OrderStartedShipping)
                .TransitionTo(Shipping),
            When(UserCancelledOrder)
                .TransitionTo(Cancelled)
                .Then(context => context.Saga.CancellationReason = "Cancelled by user")
        );

        During(Shipping,
            When(OrderDelivered)
                .TransitionTo(Delivered),
            When(UserCancelledOrder)
                .TransitionTo(Cancelled)
                .Then(context => context.Saga.CancellationReason = "Cancelled by user")
        );

        During(Created, Paid, Shipping,
            When(OrderPaymentFailed)
                .TransitionTo(Failed),
            When(OrderShippingFailed)
                .TransitionTo(Failed)
        );

        DuringAny(
            When(UserCancelledOrder)
                .Then(context => 
                {
                    Console.WriteLine($"Order {context.Saga.CorrelationId} cancelled by user.");
                })
        );
    }

    public State Created { get; private set; }
    public State Paid { get; private set; }
    public State Shipping { get; private set; }
    public State Delivered { get; private set; }
    public State Cancelled { get; private set; }
    public State Failed { get; private set; }

    public Event<OrderPlacedEvent> OrderPlaced { get; private set; }
    public Event<OrderPaidEvent> OrderPaid { get; private set; }
    public Event<OrderStartedShippingEvent> OrderStartedShipping { get; private set; }
    public Event<OrderDeliveredEvent> OrderDelivered { get; private set; }
    public Event<OrderPaymentFailedEvent> OrderPaymentFailed { get; private set; }
    public Event<OrderShippingFailedEvent> OrderShippingFailed { get; private set; }
    public Event<UserCancelledOrderEvent> UserCancelledOrder { get; private set; }

    public Schedule<OrderSagaState, ExpirationTimeoutMessage> ExpirationTimeout { get; private set; }
}

public class ExpirationTimeoutMessage
{
    public Guid OrderId { get; set; }
}
Leave a Comment