2012-06-29 35 views
3

基准信息: 我正在使用外部OAuth提供程序进行登录。如果用户登录到外部OAuth,则可以进入我的系统。但是,这个用户可能还不存在于我的系统中。这不是一个真正的技术问题,但我使用JOliver EventStore来评估它的价值。使用CQRS和EventStore创建并发

逻辑:

  1. 我没有给新用户的GUID。我只有一个电子邮件地址。
  2. 我发送一个命令前检查我的读取模型,如果用户电子邮件 存在,我发出带有ID的登录命令,如果没有,我发出带有生成ID的 CreateUser命令。我的问题是在新用户的情况下。
  3. 使用新ID在事件存储中发生保存。

问题: 假设有两种创建读取模型由于浏览器刷新或与实现读取模型的一致性之前发生其他异常更新之前命令莫名其妙发出。没关系,这不是我的问题。

会发生什么: 因为新的ID是一个GUID梳子,还有没有机会的情况下店将知道这两个CREATEUSER命令代表相同的用户。当他们到达阅读模型时,阅读模型将知道(因为他们有相同的电子邮件),并可以合并两个记录或采取其他补偿行动。但是现在我的阅读模型与事件存储不同步,它仍然认为这是两个独立的实体。

也许它并不关系,因为:

  1. 重播事件会对读取模型 同样的效果,这样应该没问题。
  2. 因为这两个命令都是重复的“创建”命令,它们应该包含相同的信息,所以它不像我在事件存储中丢失任何东西。

任何人都可以说明他们是如何处理类似的问题吗?如果某些补偿行为需要发生,读取模型服务会在发现重复条目​​时发出某种补偿命令?有没有更简单的方法我不考虑?

谢谢!

回答

7

你非常接近我认为可能的解决方案。如果我可以总结一下,这种情况有点像这样:

  • 执行OAuth-entication。
  • 根据电子邮件地址,使用读取的模型根据定期访问者和新访问者之间的决定。
  • 在新访问者的情况下,发送RegisterNewVisitor命令消息,该消息被处理并存储在事件存储中。
  • 假设存在一些并发性,对于同一个电子邮件地址,会生成两个RegisterNewVisitor消息,每个消息都包含系统认为与电子邮件地址关联的密钥。这些键(guid)是不同的。
  • 在读取模型中检测到此重复键问题,并将两个读取的模型记录合并到一个记录中。

现在不是在读模型合并的记录,为什么不把一个ResolveDuplicateVisitorEmailAddress {键,键2}对你的域模型,留给了域模型(商业决策的编纂形式采取)来解决这个问题。你甚至可以有一个专门的读取模型来处理这些类型的问题,其他的读取模型只会得到一种DuplicateVisitorEmailAddressResolved事件,并将其投影到正确的记录中。

警告标语:您提出了一个技术问题,我向您提供了技术性的,可能的解决方案。一般来说,除非我有一些业务指标值得投资,否则我不会应用这种技术(用户第一次同时登录的频率是多少 - 也许这样解决这个问题只是一种忽略根本原因的方法(flauth OAuth,没有注册新的访问者进程等))。这个问题还有其他的技术解决方案,但我想给你一个最接近你已有的东西。它们的范围从顺序注册新访问者到保留尚未读取模型的访问者的内存映射。

+0

我的观点是,这是一个属于领域模型的决定,你应该追求这一行动。 –

+3

只是要完成 - 这已多次讨论 - http://codebetter.com/gregyoung/2010/08/12/eventual-consistency-and-set-validation/ –

+0

很好回答,感谢您对该主题的了解。我确信这已经被多次回答了,但是CQRS总的来说很难找到确切的答案,因为它们如此分散。我也同意我可能会过度复杂化并不重要的情况。在这种情况下,我可能不需要做任何事情,但在我需要解决此问题的情况下,案件本身提出了更多“方法问题”。感谢您的答案和链接。 – swannee