Event versioning in CQRS
Asked Answered
O

5

5

We are at a point in our development cycle (asp.net mvc applciation), where we need to introduce changes to our existing commands and events (say adding/removing a few properties etc).

I have been trying to find a way to introduce commands/events versioning in the system. I have read many posts on google/stackoverflow etc but am still to see an example of code that implements it. Is there a recommended pattern one should follow when versioning. If yes any examples/snippets?

Edit: This is how far i have gotten with this

  1. i have versioned my events backwards, such that the latest will always be called the same, while the ones that go obsolete will have a suffix added to it like '_V1', '_V2' etc.

So if i have an event

public class OrderSubmittedEvent : IDomainEvent
{
    public int OrderId { get; private set; }

    public OrderSubmittedEvent(int orderId)
    {
        OrderId = orderId;
    }
}

and if i have to add a few properties i rename my event above to

public class OrderSubmittedEvent_V1 : IDomainEvent
{
    public int OrderId { get; private set; }

    public OrderSubmittedEvent_V1(int orderId)
    {
        OrderId = orderId;
    }
}

and introduce another event with the same name as my original event but with added properties, like so

public class OrderSubmittedEvent : IDomainEvent
{
    public int OrderId { get; private set; }

    public OrderSubmittedEvent(int version = 1, int orderId = 0, string customerName =  
                               "Joe blogs", string address = "Earth")
    {
        OrderId = orderId;
        CustomerName = customerName;
        Address = address;
        CurrentVersion = version;
    }

    public static int LatestVersion
    {
        get { return 2; }
    }

    public int CurrentVersion { get; set; }

    public string CustomerName { get; set; }
    public string Address { get; set; }
}

i still have to go ahead and change my code which publishes this event to include values for new properties.

  1. any given point of time when i get all my events from the event store (say, for replaying) they will always be of the same type after deserialization (in this case OrderSubmittedEvent) with new properties which were not part of the old events populated with their default values.

At the time of replaying my events i make my events go through an IEventUpgrader This first verifies if the events is the latest version available. since the type will always be the event type, this check is based on the properties "LatestVersion" and "CurrentVersion"

what does everyone think of this approach?

next todo

  1. If event is an old version publish an 'UpdateMYEVENT' Event

thanks

Overblouse answered 13/5, 2013 at 11:27 Comment(2)
are you using Event Sourcing or just message driven CQRS?Sonorous
@Sonorous - just message driven CQRSOverblouse
G
8

usually you only need to version the events, you can ignore the commands since you don't store them in the event store.

There are few ways to implement versioning.. my method is quite simple:

[Obsolete]
public class CompanyCreated
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public class CompanyCreated_V2
{
    public Guid Id { get; set; }
    public string CompanyName { get; set; }
    public string TaxNumber { get; set; }
}

You need to handle conversion of events from the old one to the new one as you read the events from the event store.

also, you need to be aware that you never remove any old event classes, hence why I decorate them as Obsolete, to let other developers know not to use the event.

Grapple answered 13/5, 2013 at 15:45 Comment(5)
@thanks for your reply. i have updated the main question with my editsOverblouse
@Overblouse not sure why you want to version "backwards", I think it can add confusion. also, your IEventUpgrader will always know the source and destination types. The event itself should not have any knowledge of its version number or hold any infrastructure information. this is the role of the IEventUpgrader as its more of an infrastructure service. technically there is nothing wrong with your proposed solution, just keep in mind maintenance, separation of concerns and subscribers to the event.Grapple
interesting. i want to use backwards versioning to make sure that i dont have to change references (where events are used) everytime i add a new version. Also how can my event NOT KNOW about its own version number when it is NAMED with a version number? do you mean not have a property? thats the only way for me to keep track of the latest version number.Overblouse
@Overblouse yes.. I was referring to the version property. you don't need it. your converter should explicitly know by TYPE how to convert Old_Class to New_Class and the logic of conversion should live there. I dont know how your converter looks like, but have a look at JOliver EventStore implementation. It looks like IUpconvertEvents<TSource, TTarget>.Grapple
Dont you think is better instead of use _Version on your class name just use package V2, V3, VN?Menispermaceous
I
5

If you are only adding & removing properties, there might be no need to version events; just ignore the serialized properties that are removed, and use sensible defaults for the ones you add.

Idiomatic answered 14/5, 2013 at 5:17 Comment(0)
Z
2

Admittedly I have not had the opportunity to try the following but I'd like go bake in the versioning from day one:

Since the full type name is relevant I would go for namespaces.

namespace Primary.Messages.V1
{
    public class CompanyCreated
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
}

namespace Primary.Messages.V2
{
    public class CompanyCreated
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string TaxNumber { get; set; }
    }
}

These could be in different assemblies and you could mark the older ones as obsolete (as suggested by Sarmaad). It may be that older version are not necessarily obsolete though.

Any ideas?

Zingale answered 15/5, 2013 at 4:54 Comment(0)
E
2

I would be cautious with mixing events and commands. They have different purposes and solve different problems.

To give a better feeling of what I mean, think of it like so Commands are more like RESTful API, client-server communication. While Event Sourcing is more of a way to store the data.

Both need versioning as a way to provide backward compatibility through immutability, but once again for different reasons. Hence implementation and exceptions are different.

I would definitely recommend a book Event Versioning by Greg Young to get more insides into versioning for event sourced systems..

I've also tried to gather some thoughts around Events and Events Evolution, Versioning and Migration.

For more information on the commanding, check out the CQRS series and particularly CQRS via HTTP.

Exocarp answered 26/8, 2020 at 6:5 Comment(0)
P
1

I am totally out of reasons while considering why would one need event-versioning the way it has been asked in question and more specifically the way it has been suggested in the answers?

I can think of only two use cases

1- the event class currently being used is deprecated and no more needed. Then that class can be tracked down in the git anytime needed. So why bother and complicate the active code by keeping the dead classes?

2- The business requirement is changed and now you need to keep the base event but you also need another similar event with some parameter differences. That can be solved in a number of ways, like decorator pattern can help to handle such variations to a great extent Alternately the new event might be representing a unique domain concept and instead of trying to force the concept into existing model, it might be better to name it more semantically and use it that way.

Palaeogene answered 31/10, 2017 at 4:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.