Event Upgrading

Also sometimes known as event upcasting. At some point you might find the need to replace a event with zero or more events. Some use cases might be:

  • A previous application version introduced a domain error in the form of a wrong event being emitted from the aggregate.
  • The domain has changed, either from a change in requirements or simply from a better understanding of the domain.

In the above cases, Akkatecture suggests that you implement an AggregateEventUpcaster<,> and then you can add your own upcast implementation by implementing IUpcast<,> on the upcaster. Lets do this with an example.

Imagine we have an OrderAggregate that emits ProductAddedEvents, due to new domain improvements or required it has been deemed necessary to have a new version of that event called ProductAddedEventV2. We make changes to the aggregate to emit the new version of the event, but we have a problem in that the old event is persisted in the event journal. To remedy this we will implement a suitable AggregateEventUpcaster<,>.

public class OrderAggregateEventUpcaster : AggregateEventUpcaster<OrderAggregate, OrderId>,
        IUpcast<ProductAddedEventV2, ProductAddedEvent>
    {
        public ProductAddedEventV2 Upcast(ProductAddedEvent aggregateEvent)
        {
            return new ProductAddedEventV2(
                aggregateEvent.AggregateId,
                /* other things to enrich the event */
                string.Empty);
        }
    }

and then our read journal hocon configuration requires the following to be added to it

akka.persistence {
    journal {
        plugin = ""akka.persistence.journal.some-plugin""
        some-plugin {
			event-adapters {
                ##fully qualified class name and assembly of the upcaster
				aggregate-event-tagger  = ""YourDomain.OrderAggregateEventUpcaster, YourDomain""
			}
			event-adapter-bindings = {
				""Akkatecture.Aggregates.ICommittedEvent, Akkatecture"" = aggregate-event-tagger
			}
        }
    }
}

Now in our order aggrege state, we only need to implement the apply method of the new aggregate event

public class OrderState : AggregateState<OrderState, OrderId>,
    IApply<ProductAddedEventV2>,
    IApply<ProductRemovedEvent>,
{
    public Products Products { get; private set; }

    public void Apply(ProductRemovedEvent aggregateEvent) 
    {
        Products.Remove(aggregateEvent.Product);
    }

    public void Apply(ProductAddedEventV2 aggregateEvent) 
    {
        Products.Add(aggregateEvent.Product);
    }
}

The event upcaster works as a normal IReadEventAdapter from akka.net