Как я могу сопоставить события в конечном автомате masstransit без использования Guid?

Я определил следующий конечный автомат в Masstransit:

public class OrderStateMachine : MassTransitStateMachine<OrderState>
{
    public OrderStateMachine()
    {
        InstanceState(x => x.Status);

        Event(() => OrderCreated, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode).SelectId(ctx => NewId.NextGuid()));

        //How should I select an id for these events?
        Event(() => OrderProvisioned, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));
        Event(() => OrderInvoiced, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));

        State(() => Created);
        State(() => Finished);

        CompositeEvent(() => OrderFinished, order => order.CompositeStatus, OrderProvisioned, OrderInvoiced);

        Initially(
            When(OrderCreated)
                .Then(context => Console.WriteLine("Order created"))
                .TransitionTo(Created));

        During(Created,
            When(OrderFinished)
                .Then(context => Console.WriteLine("Order finished"))
                .TransitionTo(Finished)
                .Finalize());

    }

    public State Created { get; set; }
    public State Finished { get; set; }

    public Event<OrderCreated> OrderCreated { get; set; }
    public Event<OrderProvisioned> OrderProvisioned { get; set; }
    public Event<OrderInvoiced> OrderInvoiced { get; set; }
    public Event OrderFinished { get; set; }

}

public class OrderState : SagaStateMachineInstance
{
    public Guid CorrelationId { get; set; }

    public string OrderCode { get; set; }
    public string Status { get; set; }
    public CompositeEventStatus CompositeStatus { get; set; }

}

public class OrderCreated
{
    public string OrderCode { get; set; }

    public OrderCreated(string orderCode)
    {
        OrderCode = orderCode;
    }
}

public class OrderInvoiced
{
    public string OrderCode { get; set; }

    public OrderInvoiced(string orderCode)
    {
        OrderCode = orderCode;
    }

}

public class OrderProvisioned
{
    public string OrderCode { get; set; }

    public OrderProvisioned(string orderCode)
    {
        OrderCode = orderCode;
    }
}

Как можно соотнести событие OrderProvisoned и OrderInvoiced с тем же экземпляром OrderState, что и первоначальное событие OrderCreated, не отправляя Guids в моих событиях, и использовать только свойство ordercode для их корреляции? Если я запускаю этот пример, я никогда не получу событие OrderFinished, если отправлены и OrderProvisioned, и OrderInvoiced, но если я добавлю Guids к событиям и сопоставлю их на основе этого Guid, оно будет выполнено правильно.

2 ответа

Решение

Я решил это, по-видимому, вы должны явно установить пользовательский коррелят в экземпляре statemachine, я ожидаю, что masstransit сделает это для меня. Итак, это адаптированный код для начального состояния:

            Initially(
            When(OrderCreated)
                .Then(context => context.Instance.OrderCode = context.Data.OrderCode)
                .Then(context => Console.WriteLine("Order created"))
                .TransitionTo(Created));

Также используется фабрика саг, но я думаю, что вы можете отбросить логику выбора, поскольку фабрика саг отменяет это, но я получаю исключение.

        Event(() => OrderCreated,
            x =>
            {
                x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode);
                x.InsertOnInitial = true;
                x.SetSagaFactory(context => new OrderState
                {
                    CorrelationId = NewId.NextGuid(),
                    OrderCode = context.Message.OrderCode
                });
                x.SelectId(context => NewId.NextGuid());
            });

Есть ли неработающий модульный тест, который можно было бы проверить, если это поведение не работает? Из приведенного выше отредактированного кода, похоже, я и ожидал, что он будет коррелирован - с использованием кода заказа. Вот как работает пример корзины.

Функция SelectId() необходима только для события, которое инициирует конечный автомат, поскольку именно здесь назначен CorrelationId. Если он не используется другими событиями, нет необходимости "выбирать" его, так как запрос (код заказа) будет делать корреляцию.

Вот как работает пример корзины покупок: https://github.com/MassTransit/Sample-ShoppingWeb/blob/master/src/CartTracking/ShoppingCartStateMachine.cs#L15

В вашем примере выше:

Event(() => OrderCreated, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode).SelectId(ctx => NewId.NextGuid()));

Event(() => OrderProvisioned, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));
Event(() => OrderInvoiced, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));

Это именно то, как я бы настроил, и кажется, что вы на правильном пути.

Другие вопросы по тегам