Reader question: Command sourcing to track workflow status

Good friend and Practical Microservices Daily reader Jesse Riggins wrote in with a question (shared with permission):

Hey Ethan, have you seen any discussion in the eventide forums or had any yourself re: command sourcing?

For me meaning making the commands basically aggregates as well and updating their statuses as the workflow they are representing changes.

Thanks for the question, Jesse!

I’ve not seen discussion of it by that name within the community, but that doesn’t mean it hasn’t happened.

Okay, thanks for the question, see you next time!

j/k

Let’s break it down. 🕺

tl;dr;

  • Commands are disposable, and there is risk in breaking from such a foundational principle
  • I don’t think there’s a generic way to look for all termination events for a given command

Why you might want to aggregate commands

When using Eventide with Message DB, commands are messages, and messages are written in a persistent manner to Message DB. When I give trainings, I harp on the fact that commands are not state, they might better be named “requests,” and you’ll never project / aggregate them. In fact, after a period of time, you could probably safely delete command messages from Message DB.

However, knowing the status of workflows seems very useful, so what would happen if we tried to leverage these stored commands as a way to check on those statuses?

The first challenge I’d see is that commands and events are written to different streams. For example, from the composite-component we worked on for the meetup over the past few months, we wrote Build commands to streams like composite:build-123 and the events for that process went into streams like composite-123. The state that would give the workflow status is in a stream separate from the command we’re using. To use that state, you’re looking at aggregating the event stream anyway.

Now, there’s no mechanical reason why you can’t hook up a consumer to a command category. If you have a long-running process vs. account-component’s Open / Opened pair, I can see the reasoning to aggregate, again, say the Build command into a view data table that displays a user’s pending builds.

I think there are better ways to deliver that insight though.

A different way to get what you’re after

First of all, as mentioned, commands are disposable. We’re free to change any rules in our system that we want to, of course, but to change that rule for some commands but not others, I think that would add risk. How would you effectively communicate to all of your teams which are disposable and which are not? Or do we just say that all commands must be treated as durable?

Second, and this is the main reason for me, I don’t think there’s a generic way to mark commands as complete.

composite-component’s Build goes through several steps and becomes Built. funds-transfer-component’s Transfer becomes Transferred, unless it gets cancelled and becomes Cancelled. These processes and any others can have as many steps in between with as many different termination conditions as the richness of your domain allows. To track the status of these workflows, you’ll need to understand each workflow anyway.

Where we don’t have a long-running process (account-component’s Open / Opened pair), the command immediately becomes Opened, and by aggregating Opened events, you’ll know the state of your Open workflows.

In a long-running process, although we don’t write them for this explicit purpose, we typically have an Initiated event that captures the initial input that feeds the process. I don’t think a command would offer anything above what this type of event does. I’d aggregate these into whatever view data you’re interested in, and then your consumer would already be hooked up to the state you care about.

Standard caveat

Let’s give the standard caveat, I’m not intimately familiar with every project every human on the planet is engaged in. This is just where my mind is what re: this question in the abstract. The particulars of Jesse’s project may warrant something different. There are no beginnings or endings to the turning of the Wheel of Technical Discussions, but this is a beginning.

Jesse, or anyone else, I hope this is useful. If it isn’t, please respond, and we can go deeper!


Like this message? I send out a short email each day to help software development leaders build organizations the deliver value. Join us!


Get the book!

Ready to learn how to build an autonomous, event-sourced microservices-based system? Practical Microservices is the hands-on guidance you've been looking for.

Roll up your sleeves and get ready to build Video Tutorials, the next-gen web-based learning platform. You'll build it as a collection of loosely-coupled autonomous services, developing a message store interface along the way.

When you're done, you'll be ready to contribute to microservices-based projects.

In ebook or in print.