loading...

Events immutability problem

oleksii_kraievyi profile image Oleksii Kraievyi ・1 min read

Hope, you all know the event sourcing. And one of its core principles, that events should be never changed or deleted. But what if you really need it ?
What problem do we have ? For example, you have a User aggregate. And this aggregate should receive UserCreated event.

{ type : "UserCreated", "version" : 1, "id" : 123, "name" : "John", "metadata" : { "city" : "Chicago" } }

Then this events are applied on read models like this

public class UserReadModel : IApply<UserCreated>
{
    public int Id { get; private set; }
    public string Name { get; private set; }

    public void Apply(IDomainEvent<UserCreated> @event)
    {
        Id = @event.Id;
        Name = @event.Name;
    }
}

And it's working for a year or something. But then manager comes and he says that : "We need to show user city on our UI!". And you don't really know what to do, because your read models are dependent on your events and, in theory, you should support replaying all events from your event store to restore the state of your read models.

If you can't update and delete your events, you can tell your application, that if the v2 of UserCreated event appears during replaying events it should work with new field, but if the v1 appears, you should emit v2 event with new fields.

And this thing is called event upgrader.

public class UserCreatedV1ToV2EventUpgrader
{
        public IDomainEvent<UserCreated> Upgrade(IDomainEvent<UserCreatedV1> v1Event) 
=> new DomainEvent<UserCreated>(new UserCreated { Id = v1Event.Id, Name = v1Event.Name, City = v1Event.Metadata["City"] });
}

Now, event sourcing becomes a little less complicated (no)

Discussion

pic
Editor guide