如何在不使用 Guid 的情况下关联公共交通状态机中的事件?
How can I correlate events in a masstransit state machine without using a 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 事件关联到与初始 OrderCreated 事件相同的 OrderState 实例,而无需在我的事件中发送 Guid,并且仅使用订单代码 属性 来关联它们?
如果我 运行 这个例子,如果同时发送了 OrderProvisioned 和 OrderInvoiced,我永远不会得到 OrderFinished 事件,但是如果我将 Guid 添加到事件并根据该 Guid 关联它们,它就会正确执行。
是否有损坏的单元测试可用于查看此行为是否不起作用?从上面编辑过的代码来看,这似乎是我希望它如何关联的方式——使用 OrderCode。购物车示例也是如此。
只有启动状态机的事件才需要 SelectId() 函数,因为这是分配 CorrelationId 的地方。如果其他事件不使用它,则不需要 "select" 它,因为查询(orderCode)会进行关联。
示例中的购物车示例是这样工作的:
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));
这正是我要配置的方式,看来您的方向是正确的。
我解决了,显然您必须在状态机实例上显式设置自定义 correlationid,我希望 masstransit 能为我做到这一点。
所以这是初始状态的改编代码:
Initially(
When(OrderCreated)
.Then(context => context.Instance.OrderCode = context.Data.OrderCode)
.Then(context => Console.WriteLine("Order created"))
.TransitionTo(Created));
也可以使用 saga 工厂,但我认为您可以放弃 selectid 逻辑,因为 saga 工厂否决了这一点,但我得到了一个例外。
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());
});
我在 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 事件关联到与初始 OrderCreated 事件相同的 OrderState 实例,而无需在我的事件中发送 Guid,并且仅使用订单代码 属性 来关联它们? 如果我 运行 这个例子,如果同时发送了 OrderProvisioned 和 OrderInvoiced,我永远不会得到 OrderFinished 事件,但是如果我将 Guid 添加到事件并根据该 Guid 关联它们,它就会正确执行。
是否有损坏的单元测试可用于查看此行为是否不起作用?从上面编辑过的代码来看,这似乎是我希望它如何关联的方式——使用 OrderCode。购物车示例也是如此。
只有启动状态机的事件才需要 SelectId() 函数,因为这是分配 CorrelationId 的地方。如果其他事件不使用它,则不需要 "select" 它,因为查询(orderCode)会进行关联。
示例中的购物车示例是这样工作的: 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));
这正是我要配置的方式,看来您的方向是正确的。
我解决了,显然您必须在状态机实例上显式设置自定义 correlationid,我希望 masstransit 能为我做到这一点。 所以这是初始状态的改编代码:
Initially(
When(OrderCreated)
.Then(context => context.Instance.OrderCode = context.Data.OrderCode)
.Then(context => Console.WriteLine("Order created"))
.TransitionTo(Created));
也可以使用 saga 工厂,但我认为您可以放弃 selectid 逻辑,因为 saga 工厂否决了这一点,但我得到了一个例外。
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());
});