RailsEventStore / rails_event_store

A Ruby implementation of an Event Store based on Active Record
http://railseventstore.org
MIT License
1.4k stars 122 forks source link

Potential issue with expected version while publishing events #1760

Closed socjopata closed 3 months ago

socjopata commented 3 months ago

It's either I am getting the https://railseventstore.org/docs/v2/expected_version/#integer wrong (most probably) or the aforementioned feature is not working as expected.

TL;DR

Using a fresh database, I would expected that providing any other expected_version than -1 for a given stream would give me a RubyEventStore::WrongExpectedEventVersion. Like the following should fail for a first event in a stream:

event_store.publish(
  event0,
  stream_name: "Order-1",
  expected_version: 1_000_000
)

but it does not fail, as expected. I would really appreciate some comment on the matter.

Just in case, I created a github repo to demonstrate the problem (you can find the the Ruby / Rails / Rails Event Store versions in the Gemfile)

Here is my expectation: https://github.com/socjopata/res_expected_version/blob/main/spec/res_spec.rb#L34 And what actually happens: https://github.com/socjopata/res_expected_version/blob/main/spec/res_spec.rb#L6

pjurewicz commented 3 months ago

Hello @socjopata, thanks for reaching out. I've looked at the tests you provided. It may be confusing but it's not an issue.

Technically RubyEventStore::WrongExpectedEventVersion is triggered by ::ActiveRecord::RecordNotUnique error, when a unique index on event_store_events_in_streams table stream and position columns is violated.

expected_verion acts here as optimistic locking. In a common scenario, when multiple concurrent threads would fetch the last event from the specific stream and try to insert another one with incremented position, only the first one will succeed. This is the case we want to check. It is uncommon to expect a version different than the position of the last event + 1. I can't think of any real-world scenario to do so.