The journeylism of @yreynhout

On CQRS, DDD(D), ES, …

Event Enrichment

Event or more generally message enrichment, the act of adding information to a message, comes in many shapes and sizes. Below I scribbled down some of my thoughts on the subject.

Metadata

Metadata, sometimes referred to as out of band data, is typically represented separately from the rest of the payload. Reusing the underlying protocol/service is the sane thing to do. HTTP, SOAP, Amazon AWS/Windows Azure API calls, Event Store‘s event metadata, etc … are just a few examples of how metadata could be carried around next to the payload. Other examples are explicit envelopes or message wrappers, such as the Transmission Wrapper and the Intermediate Control Act Wrapper in the HL7 V3 specification.
From a code perspective (and from my experience) the addition of metadata tends to happen in one place. Close to the metal boundary if you will, e.g. http handlers, message listeners, application services, etc …

Separate concerns

Sometimes you need to augment a message with an extra piece of data, but it feels more natural to make another piece of code responsible for adding that data. A typical example I can think of are things that have a name but you only have an identifier to start with. In an event-sourced domain model(*), think of an aggregate that holds a soft reference (an identifier if you will) to another aggregate, but the event – about to be produced – would benefit from including the name of the referenced aggregate at that time. Many events may fall in the same boat. Having a dedicated piece of code doing the enrichment could make things more explicit in your code.
Other times you may have a model that is computationally intensive, and adding the extra data would result in sub optimal data-access. How so? Well, each operation would require say a query, possibly querying the same data over and over again. While caching could mitigate some of this, having another piece of code do the enrichment could allow you to deal with this situation more effectively (e.g. batching). Not only that, but it could also make it very explicit what falls into to the category of enrichment and what not. This nuance may become even more important when you’re working as a team.
Sometimes the internal shape of your event may not be the external shape of your event, meaning they may need less, more, or even different data for various consumers. Whether such a transformation really is an enrichment is debatable. But assuming it is, it’s just another one of those situations where enrichment makes sense.
An advantage of doing enrichment separately is that certain things never enter your model. As an example, an aggregate in an event-sourced domain model, does it really need the version it is at or its identity(**)? Could I not tack that information onto the related events as I’m about to persist them? Sure I can. No need to drag(**) those things into my model.
The enrichment could be implemented using an explicit event enricher that runs either synchronously in your event producing pipeline or asynchronously, depending on what makes the most sense. Using event builders has proven to be a killer combo.

public class BeerNameEnricher : 
  IEnrich<BeerRecipeDescribed>, 
  IEnrich<BeerRecipeAltered> {

  Dictionary<string, string> _lookupNameOfBeerUsingId;

  public BeerNameEnricher(Dictionary<string, string> lookupNameOfBeerUsingId) {
    _lookupNameOfBeerUsingId = lookupNameOfBeerUsingId;
  }

  public BeerRecipeDescribed Enrich(BeerRecipeDescribed @event) {
    return @event.UsingBeerNamed(_lookupNameOfBeerUsingId[@event.BeerId]);
  }

  public BeerRecipeAltered Enrich(BeerRecipeAltered @event) {
    return @event.UsingBeerNamed(_lookupNameOfBeerUsingId[@event.BeerId]);
  }
}

(*): Familiarity with Domain Driven Design is assumed.
(**): Not every situation warrants this.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: