Commands, events and being idempotent

1,823 views
Skip to first unread message

Michael Ainsworth

unread,
Dec 15, 2015, 9:44:04 PM12/15/15
to DDD/CQRS
I understand that event handlers should be idempotent, in that playing them multiple times will yield the same result as if they were played once.

However, why do commands need to be idempotent? There are multiple articles online stating that commands should be idempotent, one such article being written by Jonathan Oliver (http://blog.jonathanoliver.com/idempotency-patterns/).

However, an idempotent command makes no sense to me. For example, a Cart aggregate root might have a method addProduct(), which returns a CartContentsChanged event. If you call addProduct() the first time, it adds a line item to the cart with a quantity of 1. If you call it a second time, it adds increases the line item quantity to 2.

Now when replaying the CartContentsChanged events multiple, we're always going to have the same result (proving idempotence), but can someone explain why we need idempotence with commands???

Danil Suits

unread,
Dec 15, 2015, 10:34:34 PM12/15/15
to DDD/CQRS
I was thinking on the topic of idempotent commands today as well, after reading Greg Young's comment: "And if you make commands idempotent then there are no issues."

I'm beginning to suspect that I've been confusing the application layer and the domain layer.  If the application layer addresses the idempotency concerns, then the aggregate roots are free to concentrate on the business invariant.

In other words, "command" in this context refers to the message that was sent to the application, and not the method on the aggregate root itself.

maybe?

Michael Ainsworth

unread,
Dec 15, 2015, 11:34:54 PM12/15/15
to DDD/CQRS
I must admit, it was Greg's comment more than the articles I've read (of which I think I threw in the wrong reference) that really got me questioning.

xiety

unread,
Dec 16, 2015, 2:45:25 AM12/16/15
to DDD/CQRS
However, an idempotent command makes no sense to me. For example, a Cart aggregate root might have a method addProduct(), which returns a CartContentsChanged event. If you call addProduct() the first time, it adds a line item to the cart with a quantity of 1. If you call it a second time, it adds increases the line item quantity to 2.

Now when replaying the CartContentsChanged events multiple, we're always going to have the same result (proving idempotence), but can someone explain why we need idempotence with commands???

Your command handlers must be idempotent to the same CommandId, not to the whole command arguments. Then your process managers can be stateless, and when they react to the already handled event after failure, and issue a new command to an aggregate, that command would not be processed twice by aggregate.

Michael Ainsworth

unread,
Dec 16, 2015, 3:13:41 AM12/16/15
to DDD/CQRS
Care to shed some light on how to track which command IDs have already been executed from within a command handler?

xiety

unread,
Dec 16, 2015, 3:20:01 AM12/16/15
to DDD/CQRS
If you use ES, then you can store the CommandId with your events. Filling processed list on aggregate rehydration and check new command versus it. Without ES you can just maintain commands ids list in DB, in the same transaction where you modify your aggregate.

Greg Young

unread,
Dec 16, 2015, 4:10:58 AM12/16/15
to ddd...@googlegroups.com
How do you handle your protocol with your clients who I assume talk to
you over a network? What do you do if you get a timeout when they send
you a command (say a router went down and you lost your connection)
> --
> You received this message because you are subscribed to the Google Groups
> "DDD/CQRS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to dddcqrs+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Studying for the Turing test

Danil Suits

unread,
Dec 16, 2015, 9:28:15 AM12/16/15
to DDD/CQRS
"If you use ES, then you can store the CommandId with your events. Filling processed list on aggregate rehydration and check new command versus it."

How should this work if the command in question creates a new aggregate, rather than modifying the target of the command?

Greg Young

unread,
Dec 16, 2015, 9:31:02 AM12/16/15
to ddd...@googlegroups.com
What you do is use a deterministic Guid (generates the event id
deterministically) ES handles everything past that (it is idempotent
internally)

On Wed, Dec 16, 2015 at 2:28 PM, Danil Suits <danil...@gmail.com> wrote:
> "If you use ES, then you can store the CommandId with your events. Filling
> processed list on aggregate rehydration and check new command versus it."
>
> How should this work if the command in question creates a new aggregate,
> rather than modifying the target of the command?
>
>
> On Wednesday, December 16, 2015 at 2:20:01 AM UTC-6, xiety wrote:
>>
>> If you use ES, then you can store the CommandId with your events. Filling
>> processed list on aggregate rehydration and check new command versus it.
>> Without ES you can just maintain commands ids list in DB, in the same
>> transaction where you modify your aggregate.
>>
>> On Wednesday, December 16, 2015 at 10:13:41 AM UTC+2, Michael Ainsworth
>> wrote:
>>>
>>> Care to shed some light on how to track which command IDs have already
>>> been executed from within a command handler?
>

Alexander Langer

unread,
Dec 16, 2015, 9:31:08 AM12/16/15
to ddd...@googlegroups.com
Simply check whether the aggregate has already been created.

On 16.12.15 15:28, Danil Suits wrote:
> "If you use ES, then you can store the CommandId with your events.
> Filling processed list on aggregate rehydration and check new command
> versus it."
>
> How should this work if the command in question creates a new aggregate,
> rather than modifying the target of the command?
>
> On Wednesday, December 16, 2015 at 2:20:01 AM UTC-6, xiety wrote:
>
> If you use ES, then you can store the CommandId with your events.
> Filling processed list on aggregate rehydration and check new
> command versus it. Without ES you can just maintain commands ids
> list in DB, in the same transaction where you modify your aggregate.
>
> On Wednesday, December 16, 2015 at 10:13:41 AM UTC+2, Michael
> Ainsworth wrote:
>
> Care to shed some light on how to track which command IDs have
> already been executed from within a command handler?
>
> --
> You received this message because you are subscribed to the Google
> Groups "DDD/CQRS" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to dddcqrs+u...@googlegroups.com
> <mailto:dddcqrs+u...@googlegroups.com>.

Danil Suits

unread,
Dec 16, 2015, 11:19:36 AM12/16/15
to DDD/CQRS

(Clarification: xiety introduced ES; I'm still thinking about the problem generally)

If we have a deterministic guid generator, is generating a deterministic id for the new aggregate sufficient?  Because it seems to me that could be checked by the application layer before (re)running the command (just as you might if the id of the new aggregate was supplied by the client).

There's still the race, of course -- I'm assuming that the persistence layer will prevent two copies of the new aggregate from being saved.
Reply all
Reply to author
Forward
0 new messages