[英]Applying SAGA pattern in situations where immediate feedback to user is required
想象有一個應用程序,用戶有一個錢包,他們可以用現金充值,兌現或從外部系統購買,當用戶創建新的采購訂單時,我們首先從用戶的錢包中扣除金額。 然后向外部 API 發送一個 API 調用,說用戶購買了這些商品,我們從商家那里得到了關於購買是否成功的回復。 如果購買不成功,我們會將金額退還到用戶在我們系統上的錢包中。 然而,這里的一個關鍵注意事項是商家購買 API 端點可能會返回域錯誤的錯誤響應(用戶未注冊,用戶已停用,購買少於最低允許金額或高於最大金額)並且用戶立即獲得交易是否成功的確認響應,如果不成功,我們向用戶顯示我們從外部 API 獲得的失敗原因
我想將 saga 應用到上面的流程中,但是有一些挑戰
假設我們將使用消息代理(Kafka、rabbitmq)進行異步 saga 流,我們如何向用戶返回有關事務是否成功的響應? 異步事務可能因任何原因而失敗,如果失敗,可能需要一段時間來處理重試甚至在后台回滾。
即使我們能夠讓我們說使用類似 webhooks 的東西將結果通知前端/用戶,我們將數據推送到客戶端。 超時或技術故障會發生什么? 由於流程是異步的,因此可能需要一秒鍾或一個小時才能完成。 同時,用戶應該看到什么? 如果我們顯示超時錯誤,用戶可以重試該請求並以待處理的 state 中的 2 個請求結束,這些請求將在稍后處理,但用戶的意圖只是發出一個。
我無法向用戶顯示“已創建購買”之類的成功消息,然后稍后再通知他們,原因有二:
我們如何解決這個問題? 嘗試用 saga 解決它的主要原因是確保一致性並在失敗時重試,但考慮到這一點,我們如何處理用戶交互?
這就是我通過temporal.io開源項目解決這個問題的方法:
下面是使用 Java SDK 實現上述邏輯。其他支持的 SDK 有 Go、Typescript/Javascript、Python、PHP。
public class PurchaseWorkflowImpl implements PurchaseWorkflow {
private final ActivityOptions options =
ActivityOptions.newBuilder().setStartToCloseTimeout(Duration.ofSeconds(10)).build();
private final Activities activities = Workflow.newActivityStub(Activities.class, options);
@Override
public void purchase(String accountId, Money amount, List<Item> items) {
WalletUpdate walletUpdate = activities.deductFromWallet(accountId, amount);
try {
activities.notifyItemsPurchased(accountId, items);
} catch (ActivityFailure e) {
// Create stub used to start a child workflow.
// ABANDON tells child to keep running after the parent completion.
RollbackWalletUpdate rollback =
Workflow.newChildWorkflowStub(
RollbackWalletUpdate.class,
ChildWorkflowOptions.newBuilder()
.setParentClosePolicy(ParentClosePolicy.PARENT_CLOSE_POLICY_ABANDON)
.build());
// Start rollbackWalletUpdate child workflow without blocking.
Async.procedure(rollback::rollbackWalletUpdate, walletUpdate);
// Wait for the child to start.
Workflow.getWorkflowExecution(rollback).get();
// Fail workflow.
throw e;
}
}
}
同步執行工作流的代碼
PurchaseWorkflow purchaseWorkflow =
workflowClient.newWorkflowStub(PurchaseWorkflow.class, options);
// Blocks until workflow completion.
purchaseWorkflow.purchase(accountId, items);
請注意,Temporal 確保工作流的代碼在出現各種類型的故障(包括進程崩潰)時保持運行,就好像什么也沒發生一樣。 所以所有的容錯方面都是自動處理的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.