CQRS之旅——旅程6(我们系统的版本管理) (5)

会议管理限界上下文在其Azure SQL数据库实例中的PricedOrders表中存储来自订单和注册限界上下文的订单信息。以前,会议管理限界上下文接收OrderPaymentConfirmed事件,现在它接收OrderConfirmed事件,该事件包含一个附加的IsFreeOfCharge属性。这将成为数据库中的一个新列。

CQRS之旅——旅程6(我们系统的版本管理)

Markus(软件开发人员)发言:

在迁移过程中,我们不需要修改该表中的现有数据,因为布尔值的默认值为false。所有现有条目都是在系统支持不需要付费的订单之前创建的。

在迁移过程中,任何正在运行的ConfirmOrderPayment命令都可能丢失,因为它们不再由订单聚合处理。您应该验证当前的命令总线没有这些命令。

CQRS之旅——旅程6(我们系统的版本管理)

Poe(IT运维人员)发言:

我们需要仔细计划如何部署V2版本,以便确保所有现有的、正在运行的ConfirmOrderPayment命令都由运行V1版本的工作角色实例处理。

系统将RegistrationProcessManager类实例的状态保存到SQL数据库表中。这个表的架构没有变化。迁移后您将看到的惟一更改是StateValue列中的一个新添加值。这反映了RegistrationProcessManager类中的ProcessState枚举中额外的PaymentConfirmationReceived值,如下面的代码示例所示:

public enum ProcessState { NotStarted = 0, AwaitingReservationConfirmation = 1, ReservationConfirmationReceived = 2, PaymentConfirmationReceived = 3, }

在V1版本中,事件源系统为订单聚合保存的事件包括OrderPaymentConfirmed事件。因此,事件存储区包含此事件类型的实例。在V2版本中,OrderPaymentConfirmed事件被替换为OrderConfirmed事件。

团队决定在V2版本中,当反序列化事件时,不在基础设施级别映射和过滤事件。这意味着,当系统从事件存储中重播这些事件时,处理程序必须同时理解旧事件和新事件。下面的代码示例在SeatAssignmentsHandler类中显示了这一点:

static SeatAssignmentsHandler() { Mapper.CreateMap<OrderPaymentConfirmed, OrderConfirmed>(); } public SeatAssignmentsHandler(IEventSourcedRepository<Order> ordersRepo, IEventSourcedRepository<SeatAssignments> assignmentsRepo) { this.ordersRepo = ordersRepo; this.assignmentsRepo = assignmentsRepo; } public void Handle(OrderPaymentConfirmed @event) { this.Handle(Mapper.Map<OrderConfirmed>(@event)); } public void Handle(OrderConfirmed @event) { var order = this.ordersRepo.Get(@event.SourceId); var assignments = order.CreateSeatAssignments(); assignmentsRepo.Save(assignments); }

您还可以在OrderViewModelGenerator类中看到同样的技术。

Order类中的方法略有不同,因为这是持久化到事件存储中的事件之一。下面的代码示例显示了Order类中受保护构造函数的一部分:

protected Order(Guid id) : base(id) { ... base.Handles<OrderPaymentConfirmed>(e => this.OnOrderConfirmed(Mapper.Map<OrderConfirmed>(e))); base.Handles<OrderConfirmed>(this.OnOrderConfirmed); ... }

CQRS之旅——旅程6(我们系统的版本管理)

Jana(软件架构师)发言:

以这种方式处理旧事件对于这个场景非常简单,因为惟一需要更改的是事件的名称。如果事件的属性也发生了变化,情况会更加复杂。将来,Contoso将考虑在基础设施中进行映射,以避免遗留事件污染领域模型。

在UI中显示剩余座位

做出这一改变有三个具体的目标,它们都是相关的。我们想要:

修改系统,在会议系统的读模型中包含每个座位类型的剩余座位数量信息。

修改UI以显示每种座位类型的剩余座位数量。

确保升级到V2后系统功能正常。

向读模型添加关于剩余座位数量的信息

系统要能显示剩余座位数量的信息来自两个地方:

当业务客户创建新的座位类型或修改座位配额时,会议管理限界上下文将引发SeatCreatedSeatUpdated事件。

在订单和注册限界上下文中,当注册者创建一个订单的时候,可用座位(SeatsAvailability)聚合将引发SeatsReserved、SeatsReservationCancelled和AvailableSeatsChanged事件。

备注:ConferenceViewModelGenerator类不使用SeatCreatedSeatUpdated事件。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfpgw.html