【问题标题】:Handling "effectively" duplicate commands in CQRS处理 CQRS 中的“有效”重复命令
【发布时间】:2021-02-08 22:30:17
【问题描述】:

我们有一些类似这样的代码:

public class Vehicle : Entity<int>, IAggregateRoot
{
    public async Task UpdatePassengers(UpdatePassengersCommand command, IValidatorProvider commandValidator, 
        CancellationToken cancellationToken)
    {
        await commandValidator.ValidateAndThrowAsync(command, cancellationToken);
    
        var domainEvent = new PassengersUpdatedEvent
        {
            VehicleId = Id,
            PrecintId = PrecintId,
            Passengers = new List<Passenger>(command.Passengers),
        };
    
        ApplyAndRaise(domainEvent);
    }
}

如果命令格式错误,则会验证并拒绝命令。否则,将创建并应用事件。问题是前端(我们无法控制)存在错误,导致它发送有效重复的事件。换句话说,它可能会发送乘客 Alice 和 Bob,然后不久之后它可能会发送 Bob 和 Alice。就业务而言,乘客仍然是相同的,因此无需应用更新。

应如何以及在何处执行此检查?在 UpdatePassengers 方法本身中?如果在这里,是否应该将其包装在传递给方法的另一个验证器中(也许是一个验证器针对聚合验证命令的验证器)?还是 Vehicle 实体本身应该包含这种类型的逻辑?

或者有没有我没有想到的更好的方法?

【问题讨论】:

    标签: cqrs


    【解决方案1】:

    通常的模式是您的域实体将包含状态,它充当一种对以前发生的事情的记忆;然后在已经发生的情况下处理命令。换句话说,想想“状态机”。

    ApplyAndRaise 这样的方法通常会做的一件事是修改实体的状态。所以诀窍是让该代码以一种允许您检测重复工作的方式更新实体,以便您可以跳过它

    您的示例表明某处有一个乘客列表,因此代码可能如下所示:

    public async Task UpdatePassengers(UpdatePassengersCommand command, IValidatorProvider commandValidator, 
            CancellationToken cancellationToken)
    {
        await commandValidator.ValidateAndThrowAsync(command, cancellationToken);
    
        if (! this.passengerList.equals(command.Passengers)) {
        
            var domainEvent = new PassengersUpdatedEvent
            {
                VehicleId = Id,
                PrecintId = PrecintId,
                Passengers = new List<Passenger>(command.Passengers),
            };
        
            ApplyAndRaise(domainEvent);
        }
    }
    

    2010 年,Marc de Graauw 建议 nobody needs reliable messaging,原因是:您的域逻辑应该足够智能以检测冗余更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多