Events

An event is something that happened which may result in a state change. An event can add or update instance data, as well as changing an instance's current state. The Event<T> is generic, where T must be a valid message type.

Declaring Events

In the example below, the SubmitOrder message is declared as an event including how to correlate the event to an instance.

Unless events implement CorrelatedBy<Guid>, they must be declared with a correlation expression.

public record SubmitOrder(Guid OrderId);

public class OrderStateMachine :
    MassTransitStateMachine<OrderState>
{
    public Event<SubmitOrder> SubmitOrder { get; private set; } = null!;
}

Configuring Events

public class OrderStateMachine :
    MassTransitStateMachine<OrderState>
{
    public Event<SubmitOrder> SubmitOrder { get; private set; } = null!;

    public OrderStateMachine()
    {
        Event(
            () => SubmitOrder, 
            e => e.CorrelateById(cxt => cxt.Message.OrderId)
        );
    }
}

Initiating Events

All State Machine Sagas come with the Initial state. The transition away from the Initial state is what creates an instance of the Saga.

public class OrderStateMachine :
    MassTransitStateMachine<OrderState>
{
    // public State Initial { get; private set; } 
    public State Submitted { get; private set; } = null!;

    public Event<SubmitOrder> SubmitOrder { get; private set; } = null!;

    public OrderStateMachine()
    {
        Initially(
            When(SubmitOrder)
              .Then(behaviorContext => 
              {
                var saga = behaviorContext.Saga;
                var message = behaviorContext.Message;

                saga.SomeProperty = message.SomeProperty;
              })
              .TransitionTo(Submitted)
              // Behavior Complete - Saga Persisted
        );
    }
}

Advanced Options

Like most things in MassTransit, the everyday use case of MassTransit should not need to use these options. But sometimes, you have to really dig in to make things happen.

Setting the Saga Factory

The only time is when using InsertOnInitial and you have required properties that must be present or the insert will fail. Typically with SQL and not null columns.

On events that are in the Initial state, a new instance of the saga will be created. You can use the SetSagaFactory to control how the saga is instantiated.

public class OrderStateMachine :
    MassTransitStateMachine<OrderState>
{
    public Event<SubmitOrder> SubmitOrder { get; private set; } = null!;

    public OrderStateMachine()
    {
        Event(
            () => SubmitOrder, 
            e => 
            {
                e.CorrelateById(cxt => cxt.Message.OrderId)
                e.SetSagaFactory(cxt =>
                {
                    // complex constructor logic
                    return new OrderState 
                    {
                        CorrelationId = cxt.Message.Instance 
                    };
                });
            }
            
        );
    }
}