CQRS NServiceBus UI 反馈
CQRS NServiceBus UI Feedback
我有一个 CQRS 解决方案,在 HTML/JavaScript 应用程序中利用 NServiceBus 和网络工作者。
我有场景
- WebAPI 发送命令
- CommandHandler 更新域聚合根
- CommandHanlder 将事件发布到更新读取模型的事件处理程序
- EventHandler 更新读取模型
我想在一切完成后向 UI 中的用户提供反馈(但不阻止 UI)。
我知道我可以使用Bus.Return到return从我的Bus.Send到我使用时的CommandHandler,说明它的工作已经完成。但是,一旦 Bus.Publish 触发的 EventHandlers 完成了他们的工作,我该如何提供反馈?
我可以使用 EventHandler 中的 Bus.Reply...但是如何返回到原始发件人?我真的需要使用 Saga 来完成这个吗?如果我做 ReplyToOriginator,一旦发起者收到回复,我如何将回复关联到正确的 user/UI 以通知?我是否必须在某处跟踪所有待处理通知的请求?好像太复杂了。
听起来 WebAPI 服务有兴趣了解 "Domain" 端点何时完成 XXX 工作。如果是这样的话,从域端点简单地发布一个事件就有意义了,然后任何关心正在完成的那种类型的工作的人都可以订阅这种事件类型。一个事件本质上是一个有趣的状态变化,所以如果正在完成的工作代表一个有趣的状态变化,那么发布事件就很有意义了。
如您所述,Bus.Reply() 也可以。我倾向于使用事件来避免显式 request/response 范例。
收到 event/response 后,将信息返回给 user/browser 是 WebAPI 服务的问题,因此需要某种形式的状态跟踪。 saga、数据库或内存中构造可以工作,但也可以 可以 通过在两个方向上传递一个与消息相关的 Id 来实现,这取决于你如何将信息返回给用户(例如 SignalR)。
这个问题已经被问过很多次了。
如果您查看 Udi 的 Longest Post,您会了解到命令处理程序应该永远不会失败的一般假设。正如 Greg Young 所建议的那样,它失败的可能性微乎其微,因此在这种情况下,不需要自动化来处理这么少的案例,因为它可以很容易地通过人工干预来处理。关于 UI 更新,Udi 建议(在同一个 post 中)UI 使用已在命令中发送的数据进行更新。意思是,UI 显示的是假设命令已正确处理且读取模型已更新的情况下的数据。当然,没有什么能阻止您使用 Bus.Return 或 Bus.Reply,有时您必须使用它,因为您不仅希望返回状态,还希望返回一些实际数据,但这是另一回事。在许多情况下,UI 的高负载系统都是这样工作的。 UI 显示服务器上已更新的数据。稍后,UI 会收到一个失败事件,表示出现错误并且数据已从读取模型更新,需要重复该命令。我认为最务实的方法是期待成功,而不是失败,这是系统正常工作的方式,完成后,创建一些机制来发布错误通知。如果没有收到错误,则假设一切顺利。
Vaughn Vernon 在他的 "Implementing DDD" 书中提到了这种方法,但指出尽管许多人认为它是一种有效的模式,但其他人批评它是一种 "hack"。所以,我假设目前还没有"right way"发明出来,大家根据需求和用户接受率来决定。
根据 Greg Young 关于用于事件分发的服务总线的说法,我得出结论,与使用 pub-sub 相比,具有追赶订阅的 ES 是一种更简单、更可靠的读取模型更新方式。
我认为在没有确认命令成功的情况下更新用户的 UI 不是最好的方法。
为此,我使用了一个名为 SignalR
的实时框架,您可以在其中进行服务器和客户端之间的实时调用。
CommandHandler
执行命令,然后触发事件,我主要使用大部分事件来更新读取数据和UI。
在事件处理程序中,您可以从 SignalR
集线器调用服务器方法(并专门回答您的问题,您可以通过获取他的 SignalR ConnectionId
返回原始发件人)(谷歌搜索 "signalr get client connection id") 可能会帮助您回复原始发件人)
我有一个 CQRS 解决方案,在 HTML/JavaScript 应用程序中利用 NServiceBus 和网络工作者。
我有场景
- WebAPI 发送命令
- CommandHandler 更新域聚合根
- CommandHanlder 将事件发布到更新读取模型的事件处理程序
- EventHandler 更新读取模型
我想在一切完成后向 UI 中的用户提供反馈(但不阻止 UI)。
我知道我可以使用Bus.Return到return从我的Bus.Send到我使用时的CommandHandler,说明它的工作已经完成。但是,一旦 Bus.Publish 触发的 EventHandlers 完成了他们的工作,我该如何提供反馈?
我可以使用 EventHandler 中的 Bus.Reply...但是如何返回到原始发件人?我真的需要使用 Saga 来完成这个吗?如果我做 ReplyToOriginator,一旦发起者收到回复,我如何将回复关联到正确的 user/UI 以通知?我是否必须在某处跟踪所有待处理通知的请求?好像太复杂了。
听起来 WebAPI 服务有兴趣了解 "Domain" 端点何时完成 XXX 工作。如果是这样的话,从域端点简单地发布一个事件就有意义了,然后任何关心正在完成的那种类型的工作的人都可以订阅这种事件类型。一个事件本质上是一个有趣的状态变化,所以如果正在完成的工作代表一个有趣的状态变化,那么发布事件就很有意义了。
如您所述,Bus.Reply() 也可以。我倾向于使用事件来避免显式 request/response 范例。
收到 event/response 后,将信息返回给 user/browser 是 WebAPI 服务的问题,因此需要某种形式的状态跟踪。 saga、数据库或内存中构造可以工作,但也可以 可以 通过在两个方向上传递一个与消息相关的 Id 来实现,这取决于你如何将信息返回给用户(例如 SignalR)。
这个问题已经被问过很多次了。
如果您查看 Udi 的 Longest Post,您会了解到命令处理程序应该永远不会失败的一般假设。正如 Greg Young 所建议的那样,它失败的可能性微乎其微,因此在这种情况下,不需要自动化来处理这么少的案例,因为它可以很容易地通过人工干预来处理。关于 UI 更新,Udi 建议(在同一个 post 中)UI 使用已在命令中发送的数据进行更新。意思是,UI 显示的是假设命令已正确处理且读取模型已更新的情况下的数据。当然,没有什么能阻止您使用 Bus.Return 或 Bus.Reply,有时您必须使用它,因为您不仅希望返回状态,还希望返回一些实际数据,但这是另一回事。在许多情况下,UI 的高负载系统都是这样工作的。 UI 显示服务器上已更新的数据。稍后,UI 会收到一个失败事件,表示出现错误并且数据已从读取模型更新,需要重复该命令。我认为最务实的方法是期待成功,而不是失败,这是系统正常工作的方式,完成后,创建一些机制来发布错误通知。如果没有收到错误,则假设一切顺利。
Vaughn Vernon 在他的 "Implementing DDD" 书中提到了这种方法,但指出尽管许多人认为它是一种有效的模式,但其他人批评它是一种 "hack"。所以,我假设目前还没有"right way"发明出来,大家根据需求和用户接受率来决定。
根据 Greg Young 关于用于事件分发的服务总线的说法,我得出结论,与使用 pub-sub 相比,具有追赶订阅的 ES 是一种更简单、更可靠的读取模型更新方式。
我认为在没有确认命令成功的情况下更新用户的 UI 不是最好的方法。
为此,我使用了一个名为 SignalR
的实时框架,您可以在其中进行服务器和客户端之间的实时调用。
CommandHandler
执行命令,然后触发事件,我主要使用大部分事件来更新读取数据和UI。
在事件处理程序中,您可以从 SignalR
集线器调用服务器方法(并专门回答您的问题,您可以通过获取他的 SignalR ConnectionId
返回原始发件人)(谷歌搜索 "signalr get client connection id") 可能会帮助您回复原始发件人)