将CQRS应用于信用卡收费(使用AKKA)

时间:2015-10-24 22:24:58

标签: akka cqrs

鉴于我对CQRS有点困惑,我想进一步了解它的情况如下:

我有一位演员向用户的信用卡收费。为此,请联系执行操作的银行外部服务,获取确认结果。

我想知道如何将其应用于CQRS?

此处需要写入的信息是特定用户已收取一定金额。因此生成的事件是Charged(UserID,Card,Amount)。这样的事情。

问题在于,我特别使用AKKA看到的所有示例都只会在验证命令后生成事件,以便它保存在日志中,并用于更新actor的状态。然后,期刊可能会在另一边变红,以便在此处创建阅读视图。

同样通常,在这些示例中,更新状态函数具有稍微执行命令的逻辑,因为该命令直接对应于当天结束时的状态更新。这是典型的BasketShoping示例:CreateOrder,AddLineItem。 All Of this Command,直接在Event中翻译,对应于Update状态函数的特定代码。

然而,在此示例中,需要实际联系外部服务,向用户收费然后生成事件。无法在更新状态或阅读日志后联系外部服务。这没有意义。

因此,我想知道,具体如何完成,以及何时,何时完全符合CQRS的精神。如果有人能澄清这一点,那就太好了。

非常感谢,

Maatari

1 个答案:

答案 0 :(得分:3)

我可以想到两种方法。

首先是一种简单的方法。命令为DoCharge(UserId, Card, Amount)。收到此命令后,您将呼叫外部支付服务。如果成功完成此操作,则会生成一个事件Charged(UserId, Card, Amount, TransactionId)并将其存储在日记中。

现在,当然,这不是完全安全的方式,因为您的演员在将请求发送到付款服务之后,但在收到并持续确认成功完成之前可能会崩溃。然后,您有两次向用户收费的风险。要克服这种风险,您必须使您的付款操作具有幂等性。这是怎么做的。此示例基于经典"RESTify Day trader"文章。我在这里总结一下。

您需要分两个阶段拆分付款操作。在第一个中,支付服务创建交易令牌。它只是识别交易,并且尚未执行任何财务操作。创建后,您的服务将接收标识符并将其保留在日记中。

在下一阶段,您将执行与第一阶段标识符相关联的付款。如果您的演员现在在中间失败,而在付款服务端成功执行操作,则交易令牌已经被标记为由付款服务处理,并且它不会让您向客户收取两次费用。现在,如果您重新启动失败的Actor,并且它尝试运行与现有交易令牌关联的付款,则支付服务应返回结果,如"已执行"或者这样的。当然,最后你还会将操作的结果保留在期刊中。