Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.
This blog post will cover creating Idempotent Aggregates and is apart of a series of posts related.
Please take a look any previous posts as they may give more context to the code samples below.
Idempotence is the property of certain operations in mathematics and computer science, that can be applied multiple times without changing the result beyond the initial application.
In my previous post Idempotent Commands
, I looked at creating idempotency at the persistence level if you are using an ACID compliance database.
But what happens if you aren’t? What other options do you have?
Well if you are building a domain model and are creating Aggregates, you could create idempotent aggregates.
If there is enough value and complexity, I will create a domain model with Aggregates that will contain domain behavior and business logic.
This is example is very trivial and I wouldn’t be creating an aggregate for basic CRUD.
However, if we did have a complex domain and aggregate, we can pass in an OperationId to our Aggregate, prior to calling any behavioral methods in order to check if we have already executed that operation.
Now in our Command Handler, we can call SetOperation and pass our MessageId from our Envelope<T>.
And as our previous example, here is our NancyFX Module (similar to ASP.NET Controller) which is sending our Command via MediatR
I have not brought up concurrency as this is something that will be determined based on your data storage solution.
How do you?
How do you handle idempotent commands? I’d love to hear about other implementations or uses. Comment below or on twitter.
10 thoughts to “Idempotent Aggregates”
The another approach that comes to my mind is connected with the commands being invoked on the basis of events (an event handler reacting to an event, like a projection). If you had a store that can apply total order, like the EventStore, all you need to do is remember the last position of the applied event per handler. This unfortunately doesn’t cover client generated identifiers but still could be useful to lower the size of the idempotence data.
You are referring to EventStore’s Catch-Up Subscriptions where the client keeps track of which Event it processed last? I’ve used it but have mainly been using it’s persistent and volatile subscriptions.
Yes. I haven’t read your articles yet (I’ve just skimmed through), but I will. Additionally, the projections themselves use a very same notion of checkpoints (in other way, a total order within partition) which can be seen in the projection handler API https://github.com/EventStore/EventStore/blob/release-v3.6.0/src/EventStore.Projections.Core/Services/IProjectionStateHandler.cs#L40 I really do like it that the whole database is only a stream of streams.
I’m using the same concept, but with a service bus instead of mediatr for commands. For queries, it’s basically like your code.
I suspect I’ll get into using a service bus sooner rather than later for the project i’m working on. Then just Ack back to the client and deal with any issues during processing as more events.
What are you using for a service bus?
Mine https://github.com/DomainBus/DomainBus , it’s optimised for monoliths with durability and saga support, but it’s still beta and lacks docs. I hope to talk about it at devteach though.
Nice! I’ll take a peak.
Here’s a gist https://gist.github.com/sapiens/347a33389b5404331d2cb680152e6890 to see it in action with the built-in idempotency support 😉