是否应该使用 sagas 来保持处理程序执行的进度?
Should sagas be used to persist progress in execution of a handler?
我有一个处理程序,它的工作是获取一个对象列表,并为该对象列表中的每个项目发布一个事件。这可能类似于下面的代码:
Handle(PublishListMessage message) {
foreach(var entry in message.List) {
Bus.Publish(entry);
}
}
我的用例是我希望 message.List.Count 很好,因此 foreach 循环可能需要一些时间。
因此,假设我已经处理了 100 个条目对象中的 50 个,然后 Bus.Publish(entry) 由于某种原因失败了。处理程序将根据我的重试策略重试,但是,它现在将从头开始处理所有 100 个条目。
这不太理想,所以我想在某个地方坚持进步。由于我使用 MongoDB 作为持久层,我想我可以将我的 Handler 包装在 Saga 中。 Saga 将跟踪所有已处理的条目,希望如果 Handler 失败,它将重试并检索 Saga 并记下之前取得的进展。
但是,我的快速测试让我假设在 Handler 完成执行之前不会提交 Saga(在本例中为 MongoDB)。所以对于我的用例,这没有帮助。
我的主要问题是我是否可以在 Handler 运行 完成之前的某个时刻将 Saga 提交给数据库。这给了我 Saga 的一些其他好处,而我不必在每个条目被发送以进行发布后编写自己的持久性。
我的第二个问题是,如果这确实可行,我应该在这个特定示例中这样做吗?这是对 Saga 的有效使用还是合适的替代方法?
为什么您认为 bus.Publish 会失败?这只有在您的传输出现故障时才会发生,但在这种情况下,NServiceBus 会将断路器设置为待命状态,并且整个端点将很快关闭。在这种情况下,我会为整个基础设施关闭做好准备,而不是回复某些数据库来保持您的进度状态。我看不出 saga 对你有什么帮助。如果您真的不信任 NServiceBus 作为简单发布的基础组件,您可以自己将循环状态保存在简单消息处理程序中,使用与用于 saga 相同的标识符。例如,这可能是关联 ID。没有什么能阻止您在消息处理程序中执行数据库操作,您不需要传奇。
我有一个处理程序,它的工作是获取一个对象列表,并为该对象列表中的每个项目发布一个事件。这可能类似于下面的代码:
Handle(PublishListMessage message) {
foreach(var entry in message.List) {
Bus.Publish(entry);
}
}
我的用例是我希望 message.List.Count 很好,因此 foreach 循环可能需要一些时间。
因此,假设我已经处理了 100 个条目对象中的 50 个,然后 Bus.Publish(entry) 由于某种原因失败了。处理程序将根据我的重试策略重试,但是,它现在将从头开始处理所有 100 个条目。
这不太理想,所以我想在某个地方坚持进步。由于我使用 MongoDB 作为持久层,我想我可以将我的 Handler 包装在 Saga 中。 Saga 将跟踪所有已处理的条目,希望如果 Handler 失败,它将重试并检索 Saga 并记下之前取得的进展。
但是,我的快速测试让我假设在 Handler 完成执行之前不会提交 Saga(在本例中为 MongoDB)。所以对于我的用例,这没有帮助。
我的主要问题是我是否可以在 Handler 运行 完成之前的某个时刻将 Saga 提交给数据库。这给了我 Saga 的一些其他好处,而我不必在每个条目被发送以进行发布后编写自己的持久性。
我的第二个问题是,如果这确实可行,我应该在这个特定示例中这样做吗?这是对 Saga 的有效使用还是合适的替代方法?
为什么您认为 bus.Publish 会失败?这只有在您的传输出现故障时才会发生,但在这种情况下,NServiceBus 会将断路器设置为待命状态,并且整个端点将很快关闭。在这种情况下,我会为整个基础设施关闭做好准备,而不是回复某些数据库来保持您的进度状态。我看不出 saga 对你有什么帮助。如果您真的不信任 NServiceBus 作为简单发布的基础组件,您可以自己将循环状态保存在简单消息处理程序中,使用与用于 saga 相同的标识符。例如,这可能是关联 ID。没有什么能阻止您在消息处理程序中执行数据库操作,您不需要传奇。