Ok, I realize this is hacky/bad. But bear with me…

Is it possible to use the event store’s stream version to implement a distributed numeric id assignment. For example:

Simultaneous actions on stream with maxCount = 1…

node1: read stream -> event version = 7 -> save blank event, expected version 7 -> pass -> next id = 7

node2: read stream -> event version = 7 -> save blank event, expected version 7 -> fail -> retry

read stream -> event version = 8 -> save blank event, expected version 8 -> pass -> next id = 8

Node 2 could get stuck retrying indefinitely if the load was heavy enough. But that won’t happen for my purposes (small percentage of use cases). What other issues could come up?

So, basically I’m trying to avoid having to put yet another DB in service just for the SQL identity column. As it would have to be highly available in our system, and we already have 2 databases in play (clustered event store and non-clustered read model document dbs).

I don’t need strictly serial numbers, but I do need a reference number for a certain type of aggregate. It doesn’t have to be assigned right away, either.

Right now my other best option is to have a maxCount = 1 stream like above, but from a fail-over numbering service (or maybe hilo type service) so the event store save happens only on the active node. But that’s still another failover service to manage configuration on. I used to be an admin, so maybe I’m trying to hard to save configuration points…

We’ve had an implementation of exactly this running in production for about a month.
Haven’t encountered any issues (in our case load is low, so the retry thing isn’t a problem)

Rich, are you using the version number or are you reading an event with the last issued number?

Yes process looks like:

Read one event backwards from StreamPosition.End

Write a blank event with ExpectedVersion = previous OriginalEventNumber

Repeat if you get WrongExpectedVersionException

Return OriginalEventNumber + 1

The only edge case is to handle SliceReadStatus.StreamNotFound for the very first try.

Right, thanks!

I’m curious if you GES folks see any looming issues with doing this?

I might cache it. It seems a bit heavy to use GES just for providing sequence numbers …

Another (possibly better way of doing this assuming its for creating aggregate ids would be to do an insert foo-created to the stream with expectedversion.any this will return you the id that was assigned which will be unique). You could then say WhateverHappenedEvent -> foo-xxxxx where xxxxx is the returned value). This would offer the same incrementing sequence behaviour and a subscriber could listen and figure out when your new aggregates were created (and what the streams for them are).



Hey, that’s a lot better option. Thanks!

I hadn’t intended to use this for aggregate ids, just for an external reference ID which could be assigned sometime after the aggregate was created. Although your solution could work for those as well. :wink:

This won’t be the only use for GES… the only reason I’m shoehorning it in is because I am already using GES for lots of other things and don’t want to introduce another configuration point just for the numbering.

That makes total sense then (i was thinking more about shoehorning in GES for that!).