Idempotent Commands

Idempotent CommandsIdempotence 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.

When you click the “Place Order” button on magical unicorn e-commerce site, you expect your order to be submitted only once.  You also expect that your credit card on on the order you just placed shouldn’t happen more than once.

There are different ways to handle idempotency at various levels of your application.

Persistence

Context is important.  In my context, I’m using a ACID compliant database (MySQL) for storing my current state.

I’m also using Entity Framework as my ORM for handling data/entity state changes.

I can handle idempotency right before I perform my database operation to modifying application state within a database transaction.

Message Identification

In a previous post, Identify Commands & Events, I described creating a Envelope<T> which contains a MessageId that we can use to keep track of messages that have been processed.

In my example, I’m using NancyFX, which uses Modules instead of Controllers.  Even if you are unfamiliar with Nancy, you should be able to understand the gist.

In our route we are going to add a new parameter {MessageId:Guid} which we will then use when creating our Envelope.

Handling

When we make our changes to our database model/entity, we will also attempt to add a new Idempotent object to its mapped table.  First lets create an entity that will contain our unique Id.

With our first pass, lets add a new Idempotent to the database context and check if there is a duplicate key exception.  I’m using MySQL and checking for Error Number 1062 that represents a unique key error.

SaveChangeAsync

The above code is a one way of how handle idempotent commands, however once you implement this more than once you will realize that the next step is to add another method to your Entity Framework Context that will handle the saving of the idempotent entity.

How do you?

How do you handle idempotent commands? I’d love to hear about other implementations or uses.  Comment below or on twitter.


Other Posts