2

The basic examples I have seen about Event Sourcing do not deal with out of order events, clock offsets in different systems and late events from system partitions.

I am wondering if more polished Event Sourcing implementations rely on a version stamp of modified objects?

For example, assuming that the system is rendering the entity Client with version id ABCD1234. If the user modifies the entity, the system will create an event with the modified fields AND the version id reference to which version it applies. Later the event responder would detect out of order events and merge them.

1
  • Vector clocks might be useful here.
    – Daenyth
    Aug 20 '14 at 18:01
2

I did something similar to an event sourcing system only recently. The domain needs to replay events in the correct order, but the domain model must not write an event to the store if another instance of the domain has just done so. I went with an optimistic concurrency approach. So the domain will retry its command and, if it is still valid, a new event will be created with the version incremented.

You mentioned the event responder detecting out of order events and I think that is perfectly fine. But my event responders actually do not care much for events out of order. I try to keep my data schemas designed to support append only data and if two users "modify" the same piece of data I just accept it and move on. If it's very important I break away from event sourcing.

I'm still trying to find the right balance between event sourcing and traditional operations.

0

Later the event responder would detect out of order events and merge them.

Possible, but I'm not seeing much of this in my research.

Event sourced objects don't subscribe to events, so much as they observe streams of events.

For example, a typical rehydration idiom is that the persistence component will retrieve events from the event store and assemble them into a stream, before a repository takes the stream, rehydrates the event sourced entity, and offers that entity to the application component ready for use.

Having rehydrated the entity, we can propose a modification to it, collect the events that represent that modification, and then propose that the event store append these new events to the stream. The guarantee provided by the event store is that, if the events are accepted, you'll be able to retrieve the new version of the stream with the events in the correct order.

The usual way of supporting this requirement is that the events are paired with a sequence number, which can be used to order them within the stream.

You can think of these sequence numbers being version ids, but you should probably keep in mind that they are versions of the stream, not versions of the entity that the stream represents -- not all streams of events are associated with a domain object (think user events vs domain events, or projections that merge events from multiple streams).

If you are trying to pair event sourcing with pub/sub, you'll probably have a driver responsible for rebuilding streams. And that's OK, I guess -- you are basically creating a facade so that the subscription looks like an event store. But keep in mind that only past events get published to the event store; if you are loading an entity so that you can change it, you are going to need to append to the most recent version history anyway, so are you really gaining much by trying to reconstruct the stream locally? It's probably easier to ask the event store to bring you up to date.

Projectsions/queries are the odd corner case - you are interested in the contents of the stream, but not intending to append to the stream. In particular, it's generally OK if you are "behind" in time. There, the streams provided to you by the subscribed driver are likely recent enough to publish a new projection.

Pub/Sub can still be a useful way to consume events when you don't need direct event sourcing. A typical use case here might be a process manager: an event appears in our subscription, and determine that we want to start a new process manager instance. So the event handler will schedule a task to load a new instance of that manager. The process manager, itself being event sourced, will need access to its own stream to recover its own state; but the dispatch of the event to be handled by the process manager doesn't need to event source anything, and can run right off the subscription, no driver required.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.