事件 (Event)
Claptrap 是基於事件溯源的 Actor 模式。事件自然就起到了至關重要的作用。
想要操作 Claptrap 就需要對其傳遞事件。事件也是改變 Claptrap State 的唯一參數。因此,在使用 Claptrap 構建系統時,所有的系統操作都會轉換為事件而傳入到 Claptrap 中。事件具有以下這些特點:
事件是有序的
每個事件都包含有一個唯一的序列號。在本框架中,這個序列號被稱為版本號(Version)。事件的版本號是一個從 1 開始逐 1 遞增的序列。事件的有序性,確保了狀態的計算不存在併發問題。這是狀態型數據可靠性的重要保證。
事件的有序性直接反應了 Claptrap 執行事件的先後順序。而由於需要確保這種順序,Claptrap 在執行事件時,必須逐個事件進行處理。這點恰好與 Actor 模式的單線程特性產生了天然的契合。
事件是不可變的
事件一旦產生,它就是不可變的。事件溯源,正由於事件的不可變性,才使得數據是可靠的。因為只要讀取事件,就能夠還原出任何一個事件執行之後的狀態。但不可變性並不是物理上的限制。你仍然可以修改物理存儲中的事件數據。但請注意,這是危險的以及極為不建議的行為。讓我們聯繫設計模式中的"開閉原則",經典的可以被概括為"對擴展開放,對修改封閉"。其中為什麼要強調「對修改封閉」呢?就筆者看來,對修改封閉的原因其實是因為修改所帶來的未知性。是因為過往執行的代碼片段產生的數據。他們都已經形成了一定的封閉性。他們是經過已有的測試所驗證的。如果嘗試修改他們,勢必就需要調整相應的測試,而這就更進一步加劇了修改,這可不是一件好事。事件的不可變是一種性質,更是一種要求。
那如果由於一個 BUG 導致了過往的產生事件數據不正確,現在需要修正這個 BUG,該怎麼辦呢?筆者的建議,不要嘗試修改已有的事件。應該追加新的事件和演算法來修正當前的狀態。不要去調整舊的內容。筆者認為這更符合開閉原則。開發者可以自行斟酌。
事件是永久的
事件是確保 Claptrap State 正確性的重要參數。因此,需要確保事件被永久保存。但,這不是絕對的情況,如果滿足以下條件,那麼事件就允許被丟失:
- 在遺失事件之前存在一個永久的 State 快照。
- 對應的 Claptrap 已經生命終結,永遠都不會再被啟動。
反之,如果不滿足以上的條件,那麼請必須確保在生產環境中的事件被正確的保存在持久化層,並且已經有相應的容災手段。