什么是saga?为什么使用事件驱动架构



我遇到了以下代码:

public class ShippingSaga : Saga<ShippingSagaData>,
ISagaStartedBy<OrderAccepted>,
ISagaStartedBy<CustomerBilledForOrder>
{
public void Handle(CustomerBilledForOrder message)
{
this.Data.CustomerHasBeenBilled = true;
this.Data.CustomerId = message.CustomerId;
this.Data.OrderId = message.OrderId;
this.CompleteIfPossible();
}
public void Handle(OrderAccepted message)
{
this.Data.ProductIdsInOrder = message.ProductIdsInOrder;
this.Data.CustomerId = message.CustomerId;
this.Data.OrderId = message.OrderId;
this.CompleteIfPossible();
}
private void CompleteIfPossible()
{
if (this.Data.ProductIdsInOrder != null && this.Data.CustomerHasBeenBilled)
{
this.Bus.Send<ShipOrderToCustomer>(
(m =>
{
m.CustomerId = this.Data.CustomerId;
m.OrderId = this.Data.OrderId;
m.ProductIdsInOrder = this.Data.ProductIdsInOrder;
}
));
this.MarkAsComplete();
}
}
}

从上面代码中的内容来看,sagas似乎是某种更高级别的事件协调器/控制器。这是真的吗?如果是,它们是否仅用于事件驱动体系结构?最后,sagas是基础设施的一部分吗?

第一个问题似乎得到了回答。但就责任而言,他们真正属于哪里,即基础设施?领域这些仅适用于EDA吗?

警告:有一些混淆,尤其是围绕着nserviebus对"Saga";;请参见下文。

Process Managers从根本上说就是读取模型——您可以从事件历史记录中重新构建它们,并查询它们以获得应该运行的命令列表。

它们类似于人类查看视图,并向写入模型发送命令。请参阅Rinat Abdullin的文章《进化的业务流程》,了解更多关于这一观点的信息。

它们是对业务流程的描述,也就是说,它们确定了应由聚合运行的其他决策(命令)。在实现中,它们在很大程度上是状态机——给定事件X和事件Y,流程管理器处于状态(XY),并且它将建议的命令是固定的。

如果你把状态机(纯逻辑)和副作用(与总线的交互)区分开来,我发现它们更容易思考。

public class ShippingSaga : Saga,
ISagaStartedBy<OrderAccepted>,
ISagaStartedBy<CustomerBilledForOrder>
{
public void Handle(CustomerBilledForOrder message)
{
this.process.apply(message);
this.CompleteIfPossible();
}
public void Handle(OrderAccepted message)
{
this.process.apply(message);
this.CompleteIfPossible();
}
private void CompleteIfPossible()
{
this.process.pendingCommands().each ( m=>
this.Bus.Send(m);
}
}
}

或者等价地——如果你更喜欢考虑不可变的数据结构

public class ShippingSaga : Saga,
ISagaStartedBy<OrderAccepted>,
ISagaStartedBy<CustomerBilledForOrder>
{
public void Handle(CustomerBilledForOrder message)
{
this.process = this.process.apply(message);
this.CompleteIfPossible();
}
public void Handle(OrderAccepted message)
{
this.process = this.process.apply(message);
this.CompleteIfPossible();
}
private void CompleteIfPossible()
{
this.process.pendingCommands().each ( m=>
this.Bus.Send(m);
}
}
}

因此,运输过程是根据业务域来定义的;佐贺";将该业务域与总线基础设施进行接口。关注点分离不是很美妙吗。

我使用";佐贺";引用是因为NService总线传奇并不特别适合之前使用的术语

术语saga通常用于CQRS的讨论,指的是在有界上下文和聚合之间协调和路由消息的一段代码。然而,出于本指南的目的,我们更喜欢使用术语流程管理器来指代这种类型的代码工件。这有两个原因:

  • "传奇"一词有一个众所周知的、预先存在的定义,其含义与通常理解的CQRS不同
  • 过程管理器一词更好地描述了这种类型的代码工件所扮演的角色

最新更新