上下文:我正在探索如何使用EventStoreDB (每个聚合单独的事件流)和Node.JS/TypeScript构建一个事件源系统/EventStoreDB。系统的一部分是1:1的客户支持聊天。创建聊天消息时,向用户发送推送通知,包括更新应用程序的标识号(未读消息总数)。我想知道什么是最好的方法来建模聚合/有界的上下文。
问题1:聊天消息放在哪里?
问题2:如何处理客户的未读邮件徽章计数器?
由于聊天消息本身已经是定时事件,它们似乎可以很容易地适应事件源系统。不过,我仍在寻求关于如何最好地对聚合体建模的建议:
选项A:由于每个聊天消息都有自己的生命周期(可以编辑它们,具有更新的读取状态,等等),所以ChatMessage可以是它自己的聚合。这会使聚合的数量激增(从而导致流),但对于EventStoreDB来说,这可能不是真正的问题。但是,要发送消息的通知,我们需要知道未读消息的总数(其他聚合的信息)。但是,推送通知应该如何发送"saga“/”流程管理器“(哪个是正确的术语?)知道通知要发送哪个警徽柜台吗?它是否应该根据所看到的所有事件为每个客户保留自己的状态/读取模型和当前计数器?
选项B:另一种方法可能是在客户聚合根目录下有一个消息列表。这样,客户就可以有一个未读消息数量的计数器,所有事件的折叠都会给我这个号码。但是,在这里,恐怕客户聚集根的大量聊天消息事件会妨碍“简单”的客户行为。例如,在处理customer命令时,我们首先通过折叠所有事件来获得当前状态(假设不使用快照),这意味着应用所有的聊天事件,甚至只是用客户的当前名称来做一些事情。
选项C:还是应该在不同的有界上下文中?那么,客户是否将其联系人详细信息放在有界的上下文中,并有一个单独的有界上下文用于聊天(或一般情况下的通信),其中两者都有一个客户聚合根共享,只共享客户的UUID?这是最好的两个世界,还是会带来其他挑战?
有什么选择吗?或者还有其他更好的选择?或者我只是完全忽略了这一点;) (不想排除这一点)
任何建议都非常感谢!
发布于 2021-02-23 20:17:55
event描述了一种(重新)创建状态的方法,方法是将每个更改存储为一个事件。这不包括这些事件是如何持久化或快照的,也不包括如何读取和分发这些事件。
我总是从用户界面开始。因为在那里您应该知道要显示哪些信息,以及可以执行哪些操作。
例如,可以有以下命令(或由用户界面执行的操作):
SendMessage(receiverId, content)MarkMessageAsRead(messageId)然后,服务器将检查所提供的数据是否有效,并创建相关事件:
class SupportChatMessageAggregate {
MessageId messageId;
UserId senderId;
UserId receiverId;
String content;
boolean readByReceiver;
// depending on framework and personal preference, this could
// also be a method: handle(SendMessage command, CurrentUser currentUser)
constructor(SendMessage command, CurrentUser currentUser) {
validate(command); // throws Exception if invalid
// for example if content is empty,
// or if currentUser is not allowed to send messages to receiverId
publishEvent(new MessageSentEvent(
command.getMessageId(),
currentUser.getUserId(),
command.getReceiverId(),
command.getContent()
));
}
handle(MarkMessageAsRead command, CurrentUser currentUser) {
validate(command); // throws Exception if invalid
// for example check if currentUser == receiver
publishEvent(new MessageMarkedAsReadEvent(
command.getMessageId(),
currentUser.getUserId()
));
}
...
}现在,当您想知道用户的徽章计数器时,只需将所有的MessageSentEvents where = currentUser相加,并减去currentUser的所有MessageMarkedAsReadEvents。
例如,这可以在UnreadSupportChatMessageCountAggregate中完成,它负责根据给定用户的MessageSentEvents和MessageMarkedAsReadEvents提供当前的unreadMessages值。一个相当无聊的集合,但它完成了工作。
这就是事件源:您只是有一堆事件,如果您想查询一些数据,只需获取所有相关事件,处理它们,并获得结果。如果每个聚合使用单独的事件流,或者所有事件只有一个流,则是实现细节(或取决于您使用的事件存储)。
这取决于事件的数量,可以非常快,也可以非常慢。这就是快照和/或读取模型(来自CQRS)派上用场的地方。但是对于普通的事件源来说,这并不是必需的。
https://stackoverflow.com/questions/66055683
复制相似问题