Deterministic Ids

So, it seems that the consensus is that using deterministic ids as event ids is a good idea in that it allows EventStore to behave as an idempotent receiver.

I’m just trying to get my head around the idea so please forgive the dumb questions:

  • If we use, for example, the GuidUtililty to generate a deterministic id does that mean we pass it a hash of the properties of an event?
  • If so, does then mean that the properties of an event published to a stream must be unique for all time?

You can get around this by including the version number you expect that event to be at in your hashing calculation.

Joao, Could you possibly explain what you mean by version number here? Thank you.

Every event is identified by stream/id (when writing) and also by
messageid. What you want ideally is to include the expected version
and use a deterministic uuid on the messageid. If you meet these two
things you will be idempotent.

And this is where I show my ignorance of EventStore.

Every event is identified by stream/id (when writing) and also by
messageid. What you want ideally is to include the expected version
and use a deterministic uuid on the messageid. If you meet these two
things you will be idempotent.

It’s where you talk about the “expected version” that you’re losing me. If I look at the documentation then I see the following for expected version:

The event number that you expect the stream to currently be at.

Does this mean that when I publish a new event to a stream that I need to pass in the EventNumber of the event that I am in the process of handling?

You *can* pass an expected version. Let's say you write an event and
you expect it to be event 3. You pass an expected version and if say
the stream currently has 4 events in it you will get an error on your
append

So, how does that work for service instances acting as competing consumers that publish events to the stream? How can instance A know how many events are already on the stream if, at the same time, instance B is also publishing events to the same stream?

I feel I must be misunderstanding something here.

Depends if you are load balancing consumers or not.

As well it should normally work without expectedversion being set
(there are just some limits to this).

Greg

Perhaps it would help if I use the canonical example of a bank transfer.

On the 1st of every month I pay a direct debit of £100 to my utility company. An event is published to the EventStore indicating this.

On the 1st of February the following event was published:

Destination Acct No: 123
Source Acct No: 234
Amount: £100

All fine.

On the 1st of March while the bank was executing my direct debit their system crashed. The transfer was effected and an event was published to the EventStore just before the system went down. When the system comes back up it republishes the same event to EventStore.

So, on the 1st of March two events were published:

Destination Acct No: 123
Source Acct No: 234
Amount: £100

and (again)

Destination Acct No: 123
Source Acct No: 234
Amount: £100

So, I guess my question is: what is the recommended way of ensuring that the events published on the 1st of March are treated idempotently i.e. the retry is effectively ignored by EventStore?

"So, I guess my question is: what is the recommended way of ensuring
that the events published on the 1st of March are treated idempotently
i.e. the retry is effectively ignored by EventStore?"

Providing they have the same EventId yes.

Try

curl -i [email protected] "http://127.0.0.1:2113/streams/newstream" -H
"Content-Type:application/json" -H "ES-EventType: SomeEvent" -H
"ES-EventId: C322E299-CB73-4B47-97C5-5054F920746E"

Then try it again. Now look at newstream in the stream browser (only
one event there!)