2014-11-22 71 views
1

我正在開發旅行行程預訂引擎。用例是這樣的:什麼是用異步事件實現狀態引擎的正確方法?

  1. 客戶預訂一個涉及多個腿(一條腿是旅程的連續部分,由同一家公司工作)的旅程。例如。從亞特蘭大到新德里的旅行可能由兩條腿組成,亞特蘭大 - 紐約和紐約 - 新德里。

  2. 每條腿都有自己的保留,可以處於「掛起」或「確認」狀態(這實際上只是真實狀態的捷徑)。

  3. 一旦預訂合作伙伴(例如,航空公司)確認預訂,每個支票預訂只允許從「掛起」轉換到「確認」。這些是可能需要數秒至數天的異步事件。

  4. 所有支票預訂都捆綁在代表客戶預訂狀態的父預訂中。只有在a)所有相關支線均「確認」後,才允許家長預訂從「掛起」轉換爲「確認」,以及b)客戶支付完成後。請注意,實際上「預訂確認」和「付款確認」存在區別,但爲簡潔起見,我在此簡化。

  5. 所有通信都是通過異步服務接口進行的,即可能需要幾秒到幾天的時間,直到收到支付預訂或支付的確認。

請注意,行程預訂子系統與支付子系統是分開的,即預訂系統只能通過查詢兩個子系統來確定父預留狀態。兩個子系統都會收到異步事件,並且在發生某些事件時也會對預訂系統執行回調。

另外請注意,該系統應該用於不同的客戶,每個客戶可以擁有自己的一組狀態/轉換(用於父級保留)。

問題:

  • 什麼是管理中心,即父母預訂的狀態常用的方法,它依賴於外部子系統的狀態?

  • 特別是,考慮到子系統確認的異步性,如何跟蹤各個子狀態?

  • 是否有組件開箱即可實現這樣的分佈式FSM(在Python生態系統中)?

我一直在思考以下方法:

  1. 實現一個「父預約FSM」反覆嘗試從「待定」到「確認」,每次查詢相應的開關的狀態付款和支付預留狀態。在這種情況下,FSM主動嘗試進入下一個狀態(或在某個時刻超時)。這將作爲一個週期性的芹菜任務來實現,它很簡單地查詢子系統,例如每30-60秒。

  2. 實現一個抽象的FSM(即工作流),該FSM在其狀態發生變化時接收來自每個子系統的回調。在這種情況下,FSM跟蹤收到的所有回調/事件,並且一旦收到所有腿事件的「付款正常」和「腿正常」,它就會將狀態切換爲「確認」。在這種情況下,FSM被動地等待事件到達。這將作爲父保留對象來實現,該對象跟蹤它收到的回調,然後設置父保留的狀態。

第一種方法沒有出現可擴展性,而第二種方法有不得不單獨跟蹤狀態的缺點。我真正想要的是一個組件,它可以解決這個問題,而不必明確型號代碼,允許爲父預留FSM設置任意配置。

實現在Python中,使用Celery/RabbitMQ和Django。

+0

我不明白你對你提出的第二個解決方案的看法。你說它必須跟蹤每個組件的狀態,這是不利的。但是,如果每個組件都可以從掛起轉換到確認,您是不是在跟蹤它們? – 2014-11-22 21:23:06

+0

@加里凱恩斯,是的,每個組件都跟蹤它們。我的意思是預訂系統將複製每個組件的狀態跟蹤。所以預訂系統基本上重新實現了子系統的FSM,這就是我的缺點。 – miraculixx 2014-11-22 22:12:10

回答

2

你的第二個選項的建議的細化:

  1. 創建的中間對象/數據庫中的表稱爲像PendingBookings。其中的數據是主要預訂的外鍵和未決腿數。我在這裏假設,在初始預訂時待處理腿的數量將不爲零。
  2. 每當創建一條腿時,其保存方法也會增加PendingBookings對象中相應的未決腿數。
  3. 無論何時確認一條腿,其保存方法也會減少未決腿數。
  4. 當掛起的支腿數量達到0時,其保存方法將啓動一個事務,將主要預訂更新爲已確認狀態並刪除PendingBookings實例。

這意味着您不必反覆輪詢物品,並且還可以爲您提供一個位置,以查找有關已開始但尚未完成的所有預訂的信息。然後,您可以不那麼頻繁地進行調查,可能每天一次進入一個OLAP多維數據集,以獲取有關通過系統進行預訂的信息。

我還會爭辯說這裏沒有重複 - 您將有用的狀態信息存儲在一個地方,並在您不再需要時將其消除。

+0

謝謝你的回答,Garry。我不確定我喜歡倒計時,因爲它不是冪等的。考慮到中間表將接收狀態更新作爲消息(即web服務調用或通過異步消息傳遞),系統將需要準確一次的語義和可靠的消息傳遞,這相對難以實現。 – miraculixx 2014-11-29 17:44:51

相關問題