Singleton aggregate root?

856 views
Skip to first unread message

Marnix Klooster

unread,
Aug 7, 2012, 11:40:28 AM8/7/12
to ddd...@googlegroups.com
Hello all,

I've been stuying Greg Young's project (https://github.com/gregoryyoung/m-r), and I have a question.

Suppose that I want to extend that sample to validate that all inventory items have unique names: how would I go about that?

It seems that I would need to introduce the concept of 'the list of all inventory items', so a separate aggregate root which is actually a singleton.  Is that correct?

If so, would I do a one-time GUID generation, and just hard-code that GUID in my code (probably in the domain model), as the id for the singleton 'list of all inventory items'?

Or is there some other way of handling 'singleton aggregate roots', or is there a way of avoiding them?

(This sounds like it is an FAQ, but I can't seem to find any answers in this group or elsewhere.  Or it is so simple that everyone just does what I described above. :-)

Thanks!

Groetjes,
 <><
Marnix "CQRS/DDD newbie" Klooster

Greg Young

unread,
Aug 7, 2012, 11:54:21 AM8/7/12
to ddd...@googlegroups.com
Something like this?
http://codebetter.com/gregyoung/2010/08/12/eventual-consistency-and-set-validation/
--
Le doute n'est pas une condition agréable, mais la certitude est absurde.

Greg Young

unread,
Aug 7, 2012, 12:00:33 PM8/7/12
to ddd...@googlegroups.com
Also .. You can make the key the Id if you use strings as keys :)

Philip Jander

unread,
Aug 7, 2012, 12:45:40 PM8/7/12
to ddd...@googlegroups.com
Hi,
>
> Suppose that I want to extend that sample to validate that all
> inventory items have unique names: how would I go about that?
>
> It seems that I would need to introduce the concept of 'the list of
> all inventory items', so a separate aggregate root which is actually a
> singleton. Is that correct?
yes. I use the same concept for providers of serial numbers (e.g.
invoice numbers, account numbers).
>
> If so, would I do a one-time GUID generation, and just hard-code that
> GUID in my code (probably in the domain model), as the id for the
> singleton 'list of all inventory items'?
yes
>
> Or is there some other way of handling 'singleton aggregate roots', or
> is there a way of avoiding them?
No reason to avoid them imho. If you have a lot of these things, I would
consider maybe putting them into a non-event sourced context. But for
the occasional uniqueness constraint, its usually less hassle to just
put that singleton into the same context where its companions are. If
(and that's a big if) you can limit your context to single server +
single thread, i.e. no sharding, you can even get away without a saga
coordinating the resource creation and uniqueness constraint.

Cheers
Phil

Alexey Raga

unread,
Aug 8, 2012, 5:18:44 AM8/8/12
to ddd...@googlegroups.com
Hi Greg, 

I like this post and yes, we can pre-validate user's email using eventually consistent store before sending a command.
But I think the real question was how to validate a command when we are within an aggregate so the aggregate publish either UserRegistered or DuplicationFound event? Assuming this aggregate is implemented with ES.

Within the aggregate we cannot just publish UserRegistered event all the time, and then consume it in some projection in order to update our eventually consistent store (which will have that unique constraint). Because it will fail and it was you who said "events represent things from the past and should never fail" :)
Also who is responsible to act on this failure then?

Cheers,
Alexey.

Greg Young

unread,
Aug 8, 2012, 6:02:41 AM8/8/12
to ddd...@googlegroups.com
> I like this post and yes, we can pre-validate user's email using eventually
> consistent store before sending a command.
> But I think the real question was how to validate a command when we are
> within an aggregate so the aggregate publish either UserRegistered or
> DuplicationFound event? Assuming this aggregate is implemented with ES.

A few things need to be looked at first.

1) How likely is this to happen?
2) What is the impact of it happening (a powerful question here is "if
this happened who would be the first person to notice and why".

Very often we spend too much time working with things from a systems
perspective when these types of risks are better mitigated through by
a business perspective. There are many heuristics that can be used to
lower the probability of something like this happening to a point that
it may happen once in the next five years in your busy system. One
question I like to ask is "Can we detect that this happened", if so
then often we can use a reactive instead of a preventative approach to
risk management.

That said.

You can have full consistency for such things on the command side
quite easily. Drop in an infrastructure service that inserts into a
table with a unique constraint as part of processing your command.
There are however trade offs with this. The largest is what happens if
that is down? Do you really want to reject the transaction?

There is another trick here for this particular problem, you can use
the natural key (user id) as the aggregate id in which case you will
be fine here as they will write back to the same event stream.

Also keep in mind that all of this is discussing a distributed
environment. If you have a single command processing server just
remember the last N users you created and check against it.

Cheers,

Greg

Alexey Raga

unread,
Aug 8, 2012, 6:23:14 AM8/8/12
to ddd...@googlegroups.com
I see.
I don't have any concern about how this failure impacts business. Say, this impact is very, very limited.
My concern was that if this event is published and there is the view holding such a constraint, it just breaks the view, full stop. And replay will not help - it breaks again. So the concern is only technical: if we allow this to happen with low probability and very low business impact, we still need to handle this failure and to react to it somehow

Using email as a natural key for an aggregate will work in this scenario, good trick :)

Cheers,
Alexey.

Greg Young

unread,
Aug 8, 2012, 6:24:58 AM8/8/12
to ddd...@googlegroups.com
Actually you would allow the projection to accept having two.

But detect in another place that the problem had happened (and say
email an admin).

@yreynhout

unread,
Aug 8, 2012, 6:29:44 AM8/8/12
to ddd...@googlegroups.com
If it's low business impact, please explain why you'd invest into it only at a technical level? Sounds like programmer pornography to me.

Jeff Harris

unread,
Nov 22, 2014, 3:11:12 PM11/22/14
to ddd...@googlegroups.com
(just replying to last message on thread)

+1 for Greg's comment on RM handling duplicates: It should be possible to handle this case *somehow* (e.g. if you already have a value here with this key, just ignore the new value -- first-in-wins)

I think I'd probably follow Greg's advice: http://codebetter.com/gregyoung/2010/08/12/eventual-consistency-and-set-validation/


A thought on natural keys: just be the general concern that if your natural key is a value that can be changed, you have another set of issues.

For that matter, if the product name / email can be changed, you have the possibility you could have a unique value being changed to a value that is no longer unique.

If you're checking the read model before you take these actions, this is a low-risk scenario -- just make sure it doesn't bring down your whole system, and that you have some way to notice it.


Reply all
Reply to author
Forward
0 new messages