NServiceBus Saga 是企业集成模式一书中描述的流程管理器的变体。
要了解何时使用 Saga,必须先了解它。假设您仅使用常规消息处理程序来实现新用户注册过程。在某个时间点,您发现只有 40% 的全新注册人确认他们的电子邮件地址并成为活跃用户帐户。您想解决两件事。
- 在注册后 24 小时后,通过发送提醒来提醒新注册人确认他们的电子邮件。
- 在 48 小时内从数据存储中删除注册人信息(例如电子邮件)以符合GDPR 。
现在,您如何使用常规消息处理程序来做到这一点?处理程序将通过生成带有确认链接的电子邮件来接收初始请求(第一条消息,m1)以启动注册,仅此而已。一旦处理程序完成,它就永远完成了。但是你的过程还没有结束。这是一个长期运行的逻辑过程,必须跨越 48 小时才能完成。它不再只是单个消息处理,而是此时的工作流。具有多个检查点的工作流程。类似于状态机。要从一种状态转移到另一种状态,必须满足某个条件。在 NServiceBus 的情况下,这些将是消息。任何用户操作都不会触发 24 小时后发送提醒的消息(我们称之为 m2)。这是一个“系统”消息。应自动启动的定时消息。指示系统删除注册人信息的消息也是如此验证链接未激活。可以观察到主题:需要在未来安排消息以重新水合工作流程并从上次离开的状态继续。
这就是超时。这些是从上次在某个时间点(分钟、小时、天、月、年)离开的点重新补充/继续传奇/工作流程的请求。
这就是这种工作流程看起来像传奇的样子(过于简化并且没有考虑所有边缘情况)。
class RegistrationWorkflow :
Saga<WorkflowState>,
IAmStartedByMessages<RegisterUser>,
IHandleMessages<ActivationReceived>,
IHandleTimeouts<NoResponseFor24Hours>,
IHandleTimeouts<NoResponseFor48Hours>
{
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<WorkflowState> mapper)
{
// omitted for simplicity, see message correlation
// https://docs.particular.net/nservicebus/sagas/message-correlation
}
public async Task Handle(RegisterUser message, IMessageHandlerContext context)
{
Data.RegistrationId = message.RegistrationEmail;
await RequestTimeout<NoResponseFor24Hours>(context, TimeSpan.FromHours(24));
}
public async Task Handle(ActivationReceived message, IMessageHandlerContext context)
{
Data.ConfirmationReceived = true;
// email was confirmed and account was activated
await context.Send(new PromoteCandidateToUser
{
CandidateEmail = Data.RegistrationEmail
});
MarkAsComplete()
}
public async Task Timeout(NoResponseFor24Hours timeout, IMessageHandlerContext context)
{
if (Data.ConfirmationReceived)
{
return;
}
await context.Send(new SendReminderEmailToActivateAccount { Email = Data.RegistrationEmail });
await RequestTimeout(context, TimeSpan.FromHours(24), new NoResponseFor48Hours());
}
public async Task Timeout(NoResponseFor48Hours timeout, IMessageHandlerContext context)
{
if (Data.ConfirmationReceived)
{
return;
}
context.Send(new CleanupRegistrationInformationForGDPRCompliancy
{
RegistrationEmail = Data.RegistrationEmail
});
MarkAsComplete();
}
}
由于这是一个状态机,因此状态在 Saga 调用之间保持不变。调用将由 saga 可以处理的消息 ( RegisterUser
and ActivationReceived
) 或到期的超时 ( NoResponseFor24Hours
and NoResponseFor48Hours
) 引起。对于这个特定的 saga,状态由以下 POCO 定义:
class WorkflowState : ContainSagaData
{
public string RegistrationEmail { get; set; }
public bool ConfirmationReceived { get; set; }
}
超时只不过IMessage
是被推迟的普通s。此示例中使用的超时将是
class NoResponseFor24Hours : IMessage {}
class NoResponseFor48Hours : IMessage {}
希望这能总体上阐明Sagas的概念,什么是超时以及如何使用它们。我没有进入Message Correlation、Saga Concurrency和其他一些细节,因为这些细节可以在您提到的文档站点上找到。这将我们带到了下一点。
我已经多次阅读他们网站上的文档。这绝对是可怕的。我一遍又一遍地阅读相同的文章,我无法理解他们想要达到的目标。
该网站有一个您绝对应该提供的反馈机制。
此外,互联网上几乎没有与此主题相关的资源。
希望看到您发布有关此主题的博客(或一系列帖子)。通过这样做,您将做出积极的贡献。
完全免责声明:我在 NServiceBus 工作