2017-06-06 66 views
0

在Lagom中,當命令處理程序必須執行一些異步操作時,你會做什麼?例如:Lagom:命令處理程序中的異步操作

override def behavior = Actions().onCommand[MyCommand, Done] { 
    case (cmd, ctx, state) => 
    // some complex code that performs asynchronous operations 
    // (for example, querying other persistent entities or the read-side 
    // by making calls that return Future[...] and composing those), 
    // as summarized in a placeholder below: 
    val events: Future[Seq[Event]] = ??? 
    events map { 
     xs => ctx.thenPersistAll(xs: _*) {() => ctx.reply(Done) } 
    } 
} 

與這樣的代碼的問題是,編譯器期望的命令處理程序返回Persist,不Future[Persist]

這樣做的目的是爲了確保事件以正確的順序持續存在(也就是說,事先生成的事件必須保存在事件之後)。但是不能通過適當管理事件補償來處理,以便日記總是正確地命令它們,而不管它們何時實際保存?

在這種情況下,當命令處理足夠複雜以至於需要從命令處理程序進行異步調用時,會發生什麼情況?

回答

2

在郵件列表上還有一個類似的問題,James的答案是。 https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/lagom-framework/Z6lynjNTqgE

總之,你在CQRS應用實體是一致的邊界,應該只依賴於數據,它是立即可用裏面,不在外面(沒有調用外部服務)。

您可能正在尋找什麼叫Command Enrichment。您會收到一個請求,從外部服務收集一些數據,並構建一個包含您需要發送到您的實體的所有內容的命令。

您當然不應該詢問讀方在您的寫方實體內做出業務決策。您也不應該對來自其他實體的數據做出商業決策。

您的實體應該能夠做出所有決定,因爲它是模型的一致性邊界。

+0

這一切都很好,但是當一個聚合可以引用另一個聚合內的實體(並且一般!)時,刪除級聯的一致性邊界就變成了整個世界。當然,除非完全禁用刪除,這可能是一種選擇。 – silverberry

+0

命令濃縮是另一種選擇。謝謝。 – silverberry

+0

我想我可以做preDelete來收集所有防止刪除的實體或所有必須通過級聯刪除/更新的實體,然後纔會實際發出執行這些操作的命令。 – silverberry

1

我在這些情況下所做的是將PersistentEntityRef傳遞給異步操作,以便它可以向實體及其那些命令處理程序(不是生成異步計算的那個)發出命令,然後堅持事件。

只要記住這些都不是原子的,所以你必須考慮如果異步操作在發出命令的過程中失敗,或者如果某些命令成功並且某些命令失敗等等,會發生什麼情況。假定您需要一些系統故障的重試機制。如果你構建你的命令處理程序是冪等的,它將幫助你處理重複項。

相關問題