基于事件驱动架构构建微服务第7部分:在仓储上实现事件溯源
原文鏈接:https://logcorner.com/building-microservices-through-event-driven-architecture-part7-implementing-eventsourcing-on-repositories/
在本文中,我將討論Repository上的Event Sourcing實現。
倉儲負責將事件添加到事件存儲并從事件存儲中檢索所有事件。
保存聚合后,所有與該聚合根相關的未提交事件都會添加到事件存儲表中。
eventstore表是一個只能追加的表(不允許更新和刪除)。
eventstore表的架構如下所示:
Id 主鍵
Version 聚合的版本
AggregateId 聚合的標識符
Name 事件的名稱:2@735f8407-16be-44b5-be96-2bab582b5298
TypeName 事件的類型:LogCorner.EduSync.Speech.Domain.Events.Speech.SpeechCreatedEvent、LogCorner.EduSync.Speech.Domain、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null
OccurredOn 事件日期
PayLoad 事件流:
IsSync 指示事件是否同步的布爾值
要重建聚合的當前狀態,我們必須讀取與給定聚合ID相關的所有事件,然后調用函數LoadFromHistory。此函數屬于AggregateRoot類,應將所有事件應用于聚合。
事件溯源接口
讓我們定義IEventStoreRepository接口
GetByIdAsync 一個函數,用于從事件存儲中檢索與聚合相關的所有事件。
AppendAsync 一個將事件附加到事件存儲的函數
事件溯源實現
讓我們定義EventStore類
Id 事件流的標識符
Version 當前的聚合版本
AggregateId 聚合的標識符
Name 事件流的名稱
TypeName 事件的完整類型(例如:LogCorner.EduSync.Speech.Domain.Events.Speech.SpeechCreatedEvent、LogCorner.EduSync.Speech.Domain、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null)
OccurredOn 事件發生的日期
SerializedBody 事件序列化的JSON
AppendAsync 一個函數,用于指示事件是否已同步。
APPENDASYNC 實現
測試用例1:AppendAsync應該在eventstore上附加一個事件:
在這里,我必須模擬一個上下文,創建一個 IEventStoreRepository實例并使用EventStore對象調用AppendAsync,然后上下文應該有一組帶有單個元素的 EventStore,并且該元素應該等于我在AppendAsync的參數中傳遞的eventstore對象.
測試可能如下所示:
但是我將使用entityframeworkcore inmemory數據庫而不是使用moq,這是一種更簡單的數據庫單元測試方法。
所以我可以像這樣實例化一個內存上下文:
下一步是創建一個EventStoreRepository類
然后將DbSetEventStore屬性添加到DatabaseContex類
代碼編譯成功但測試失敗,因為DbSetEventStore為空。
所以讓我們配置一些映射
EventStoreEntityTypeConfiguration類負責將EventStore類映射到EventStore數據庫表
最終測試如下所示:
GETBYIDASYNC實現
GetByIdAsync從事件存儲中檢索與聚合相關的所有事件。
在這里,我必須創建一個Speech類型的空聚合,從與它相關的事件存儲中讀取所有事件,最后應用這些事件。
測試用例2:AggregateRoot的CreateInstance應該返回一個空的聚合
讓我們創建一個Invoker類,負責創建一個空的聚合根
測試通過
測試用例3:GetByIdAsync和BadAggregateId應該引發BadAggregateIdException
給定一個錯誤的aggregateId(例如:空的aggregateId),GetByIdAsync應該引發一個異常(BadAggregateIdException)
測試用例4:GetByIdAsyncWithNullInstanceOfAggregateShouldRaiseNullInstanceOfAggregateIdException
給定不存在的聚合ID(例如:空聚合 ID),GetByIdAsync應該引發異常 (NullInstanceOfAggregateIdException)
測試用例5:GetByIdAsyncWithoutEventsShouldReturnEmptyList
如果沒有與給定聚合ID相關的事件,則GetByIdAsync應返回一個空列表
測試用例6:GetByIdAsyncWithEventsShouldReturnTheCurrentStateOfAggregate
在這里,我必須從事件存儲中讀取與給定聚合ID相關的所有事件,重建聚合狀態并返回它。
為了達到這個目標,我必須根據事件類型反序列化json結構中的事件。
測試用例6.1:反序列化事件流應該返回一個事件
在這里,我將創建一個將json字符串反序列化為Event對象的函數
測試用例6.2:GetByIdAsyncWithEventsShouldReturnTheCurrentStateOfTheAggregate
到這里,我將完成我的函數的實現
本文的源代碼可在此處獲得 (Feature/Task/EventSourcingRepository)
https://github.com/logcorner/LogCorner.EduSync.Speech.Command/tree/Feature/Task/EventSourcingRepository
總結
以上是生活随笔為你收集整理的基于事件驱动架构构建微服务第7部分:在仓储上实现事件溯源的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微服务之 EShop on dapr概览
- 下一篇: 微服务的终极目标,Mecha分布式运行时