1

I have a CQRS system in development that passes the Command to a CommandHandler, which gets an Aggregate from a Repository, and calls a method with the properties of the Command (converted to ValueObjects).

The method then creates the Event internally and registers it in a hash object to be collected and persisted later.

I have some meta data that needs to come from the initial request and be persisted with the resulting Event, and I am loathed to have to pass this through the method on the Aggregate which IMO should be only concerned with the domain itself, and not message related data.

The problem I have is that every single public method in the domain will have to accept this meta object; that seems ridiculous to me. Even a method that normally would have no parameters (like a toggleSomeState() method).

So, my question is, can someone provide a decent example of how the meta data can bypass the Aggregate, yet end up in the Event on the other side?

Update:

Here's an explanation of the meta data. We currently have two Uuids that have been used for authentication, and due to the nature of the domain being a multi-tenanted system, these uuids have to be persisted right the way through the application. Of course, if I have two now, I will have more later ;) This is another reason I want to not pass them into the aggregate methods.

Also, from a comment, I have learned that once an Event has been produced, it is immutable. How then could I be comfortable allowing the system to edit that Event before persistence to add this meta data? Is this one of those occasions of compromise I would have to live with?

  • Would adding a method like withMetaData(...) be a good solution in people's minds? Load the aggregate from event history, call withMetaData then call domain method. Resulting events have meta data in them, and the domain API is clean. – designermonkey Apr 17 '18 at 16:17
  • Can you tell us about this metadata? That might help highlight any modelling/design oversights. – MetaFight Apr 17 '18 at 16:46
  • Knowing more about this metadata (it's intent/how it's used) would probably help. I would hesitate, though, to pass unnecessary data to the domain. There a options here. For example, adding Middleware that intercepts Events. Your CommandHandler could inject the Middleware with the metadata which would then process the Event accordingly. Remember, everything is Pipes and Filters. You have control of the messaging. – king-side-slide Apr 17 '18 at 20:48
  • This depends a lot on the framework/library that you use; the framework should handle this; indeed, the domain should not care about the metadata. As an example: github.com/xprt64/dudulina/blob/master/src/Dudulina/Command/… – Constantin Galbenu Apr 18 '18 at 8:49
  • @king-side-slide I understand your point here, sadly all this is happening deeper into the onion than the middleware layer; our architecture doesn't work like that :( It's a shame though as that is nice idea. – designermonkey Apr 18 '18 at 21:13
1

There's no magic.

The metadata has a lifetime within the request scope, so you are going to need to trace out some path from where it starts to where it ends.

Now, if it is metadata, then the domain model really shouldn't be concerned with it -- so you would prefer that the path not pass explicitly through the model.

There are at least two possibilities for how to achieve this.

One is to look at the creation of the events themselves - you could use a factory to create the new events, and inject a factory that has been initialized with the metadata. The event factory in effect acts as a collaborating interface between your domain model and the event representations that you store.

(You were already creating events within your domain logic, so the factory has at least implicit existence in your domain; all we are doing is making that existence explicit and giving it request scope).

Another possibility is to consider "appending" the metadata to the representations as you write them. Each of the event representations is transformed by adding the metadata to it, within the scope of the request, but before writing them to the store.

  • So then, I like the idea of using factories which can inject the meta data during event construction, but I am still concerned about how to get that into the Aggregate. Aggregates are constructed with their state, which results in a created event; I am uncomfortable with adding an infrastructure component in with the initial state. Also, there is the reverse action of hydrating an aggregate from it's events; Which meta data from a long history should be used, and also, where would the factory be injected then? I have a lot of thinking to do on this... – designermonkey Apr 18 '18 at 21:10
  • I think I have a solution and will post some interfaces as examples as soon as I've drafted it. I think the solution is to pass the metadata to the aggregate repository in the storeAggregate (or similar) method, that way it can be appended to the event during write to the store. – designermonkey Apr 18 '18 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.