RailsEventStore / rails_event_store

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

"Expected version" as value object #274

Closed joelvh closed 6 years ago

joelvh commented 6 years ago

I found that the "expected version" can be given in specific ways when appending events to a stream. Depending on which expectation you specify, the version to use when inserting events needs to be resolved.

The logic as to what is valid and how it's resolved seems to be very specific and each repository implementation is implementing validation independent of each other.

I created the ExpectedVersion class as a way to encapsulate validation and resolution. Admittedly, the way that resolving the version works could potentially be improved, but I'd like to get your thoughts on this as a start.

https://github.com/RailsEventStore/rails_event_store/pull/268/files#diff-8c1b6e4e8779c1dc7198c022d202fe34

cc @paneq @pawelpacana

joelvh commented 6 years ago

@paneq @pawelpacana I wonder if this encapsulation of expected version could be combined with the new Stream passed to the repository. Thoughts?

mostlyobvious commented 6 years ago

Took it a bit further in #300

joelvh commented 6 years ago

Awesome @pawelpacana! Glad to see that implemented.

mostlyobvious commented 6 years ago

I wonder if this encapsulation of expected version could be combined with the new Stream passed to the repository. Thoughts?

Simple heuristic would suggest so. It is usually passed together:

ruby_event_store/lib/ruby_event_store/client.rb
17:    def publish_events(events, stream_name: GLOBAL_STREAM, expected_version: :any)
18:      append_to_stream(events, stream_name: stream_name, expected_version: expected_version)
25:    def publish_event(event, stream_name: GLOBAL_STREAM, expected_version: :any)
26:      publish_events([event], stream_name: stream_name, expected_version: expected_version)
29:    def append_to_stream(events, stream_name: GLOBAL_STREAM, expected_version: :any)

ruby_event_store/lib/ruby_event_store/in_memory_repository.rb
13:    def append_to_stream(events, stream, expected_version)
17:    def link_to_stream(event_ids, stream, expected_version)

ruby_event_store_rom_sql/lib/ruby_event_store/rom/event_repository.rb
9:      def append_to_stream(events, stream, expected_version)
21:      def link_to_stream(event_ids, stream, expected_version)
22:        @events.link(normalize_to_array(event_ids), stream, expected_version)

rails_event_store_active_record/lib/rails_event_store_active_record/event_repository.rb
13:    def append_to_stream(events, stream, expected_version)
14:      add_to_stream(normalize_to_array(events), stream, expected_version, true) do |event|
20:    def link_to_stream(event_ids, stream, expected_version)
24:      add_to_stream(normalize_to_array(event_ids), stream, expected_version, nil) do |event_id|
71:    def add_to_stream(collection, stream, expected_version, include_global, &to_event_id)

And we could check invalid_version! if stream.global? && !any? much earlier.

joelvh commented 6 years ago

@pawelpacana close this issue since this is merged into master?