如何在事件源中处理已删除的事件类

时间:2018-08-22 06:46:44

标签: cqrs event-sourcing

我正在尝试实现纯事件源服务,以查看在哪里出现问题。现在,我发现了一个到目前为止无法解决的问题,因此我想就此进行讨论。

给出以下汇总:

class User
    {
        public Guid Id { get; private set; }

        public string Name { get; private set; }

        public void Apply(UserNameChangedEvent domainEvent)
        {
            Name = domainEvent.NewName;
        }


        public void Apply(UserCreatedEvent domainEvent)
        {
            Name = domainEvent.Name;
            Id = domainEvent.Id;
        }
    }

和那些域事件

class UserCreatedEvent
    {
        public string NewName { get; }
        public Guid Id { get; }

        public UserCreatedEvent(string newName, Guid id)
        {
            NewName = newName;
            Id = id;
        }
    }

class UserNameChangedEvent
    {
        public string NewName { get; }

        public UserNameChangedEvent(string newName)
        {
            NewName = newName;
        }
    }

可以说我创建了一个用户,然后将其名称更改为“ Peter”,然后在我的EventStore中保留了一个UserCretedEvent和一个UserChangedNameEvent。现在,企业表示不再可以更改名称,因此我将删除类UserChangedNameEvent和处理该名称的函数。但是现在我有一个问题,就是我无法以正确的状态(名称为“ Peter”)重新创建聚合。

当然,我可以开始研究,并将功能和类标记为已弃用,因此我可以继续使用它,但是此后我可能会遇到很多事件类,这将是一个噩梦,需要跟踪。我还听说您可能会创建一个新事件,该事件会保留域中的更改,但是对我来说,这似乎很棘手,而且风格也不是很好,因为从我的角度来看,这不是域事件。

问题是,我该如何最好地应对这种变化?

编辑:只是为了澄清:我不想删除任何事件,只删除我使用它的类和函数,因为现在的要求有所不同。

2 个答案:

答案 0 :(得分:1)

格雷格·杨(Greg Young)的事件模式变更相关问题的资源为Versioning in an Event Sourced System

  

问题是,我该如何最好地应对这种变化?

这取决于您要解决的实际问题。

如果要求将来不允许用户更改其名称,则可以取消域模型中创建 new UserNameChangedEvent的逻辑,但请假在事件确实出现的正确处理之后。

如果要求忽略对用户名的更改,那么您也可以使用Apply(UserNameChanged)处理程序并将其转换为NoOp,就像处理任何其他无法识别的事件一样。

如果要求删除有关名称更改的信息,则可以将事件存储迁移到新的架构,该架构不再包含UserNameChanged事件。

如果将状态存储在RDBMS中,则可能会帮助您仔细考虑如何解决问题:是否足以忽略“用户名”列?您需要删除该列吗?您是否需要(以某种方式)将列中的值恢复为先前写入的值?

在传统数据库中知道与您要在事件存储中解决的问题类似的问题,应该有助于确定适当的解决方案。

也:请注意您的域模型是否是需要更改的数据的记录系统,或者您是否正在缓存由不同机构发布的信息的表示形式。

答案 1 :(得分:1)

事件捕获了有关系统的事实。如果某个时候更改了用户名,那是事实。将来的业务规则更改不会影响过去的事实。 因此,您不应该删除UserNameChanged事件,所有相关的处理程序,事件都在那里,并且您不应该重写过去的历史记录。

在CQRS应用程序中,事件由命令处理程序生成。因此,这是您指定业务需求的地方。 “现在企业说不再可以更改名称了”,这意味着ChangeName命令不再可用:您可以简单地删除它,或者抛出一个错误消息,说您不能再更改名称。