From 1a796c75d7c19338fb00d1301bb0779be1fa8418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pacana?= Date: Sun, 4 Feb 2024 16:43:40 +0100 Subject: [PATCH 1/3] Document current behaviour more thoroughly before altering it https://github.com/RailsEventStore/rails_event_store/pull/1108 Co-authored-by: Szymon Fiedler --- .../spec/transactions_spec.rb | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 ruby_event_store-active_record/spec/transactions_spec.rb diff --git a/ruby_event_store-active_record/spec/transactions_spec.rb b/ruby_event_store-active_record/spec/transactions_spec.rb new file mode 100644 index 0000000000..a6c3f43503 --- /dev/null +++ b/ruby_event_store-active_record/spec/transactions_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +require "spec_helper" +require "ruby_event_store" +require "ruby_event_store/spec/event_repository_lint" + +module RubyEventStore + module ActiveRecord + ::RSpec.describe EventRepository do + helper = SpecHelper.new + mk_repository = -> { EventRepository.new(serializer: helper.serializer) } + + let(:repository) { mk_repository.call } + let(:specification) do + Specification.new( + SpecificationReader.new(repository, Mappers::Default.new) + ) + end + + let(:stream) { Stream.new(SecureRandom.uuid) } + let(:foo) { SRecord.new(event_id: SecureRandom.uuid) } + let(:bar) { SRecord.new(event_id: SecureRandom.uuid) } + let(:baz) { SRecord.new(event_id: SecureRandom.uuid) } + let(:global_to_a) { repository.read(specification.result).to_a } + let(:stream_to_a) do + repository.read(specification.stream(stream.name).result).to_a + end + + around(:each) { |example| helper.run_lifecycle { example.run } } + + around(:each) do |example| + ::ActiveRecord::Base.logger = + Logger + .new(STDOUT) + .tap do |l| + l.formatter = + proc { |severity, datetime, progname, msg| "#{msg}\n" } + end + example.run + ::ActiveRecord::Base.logger = nil + end + + specify "no application transaction, event_id conflict" do + repository.append_to_stream([foo], stream, ExpectedVersion.any) + + expect do + repository.append_to_stream([bar], stream, ExpectedVersion.any) + repository.append_to_stream([foo], stream, ExpectedVersion.any) + end.to raise_error(EventDuplicatedInStream) + + expect(global_to_a).to eq([foo, bar]) + expect(stream_to_a).to eq([foo, bar]) + end + + specify "no application transaction, expected_version conflict" do + repository.append_to_stream([foo], stream, ExpectedVersion.none) + + expect do + repository.append_to_stream([bar], stream, ExpectedVersion.any) + repository.append_to_stream([baz], stream, ExpectedVersion.none) + end.to raise_error(WrongExpectedEventVersion) + + expect(global_to_a).to eq([foo, bar]) + expect(stream_to_a).to eq([foo, bar]) + end + + specify "application transaction, event_id conflict" do + repository.append_to_stream([foo], stream, ExpectedVersion.any) + + expect do + helper.with_transaction do + repository.append_to_stream([bar], stream, ExpectedVersion.any) + repository.append_to_stream([foo], stream, ExpectedVersion.any) + end + end.to raise_error(EventDuplicatedInStream) + + expect(global_to_a).to eq([foo]) + expect(stream_to_a).to eq([foo]) + end + + specify "application transaction, expected_version conflict" do + repository.append_to_stream([foo], stream, ExpectedVersion.none) + + expect do + helper.with_transaction do + repository.append_to_stream([bar], stream, ExpectedVersion.any) + repository.append_to_stream([baz], stream, ExpectedVersion.none) + end + end.to raise_error(WrongExpectedEventVersion) + + expect(global_to_a).to eq([foo]) + expect(stream_to_a).to eq([foo]) + end + + specify "application transaction, event_id conflict — rescued" do + repository.append_to_stream([foo], stream, ExpectedVersion.any) + + helper.with_transaction do + begin + repository.append_to_stream([bar], stream, ExpectedVersion.any) + repository.append_to_stream([foo], stream, ExpectedVersion.any) + rescue EventDuplicatedInStream + end + end + + expect(global_to_a).to eq([foo, bar]) + expect(stream_to_a).to eq([foo, bar]) + end + + specify "application transaction, expected_version conflict — rescued" do + repository.append_to_stream([foo], stream, ExpectedVersion.none) + + helper.with_transaction do + begin + repository.append_to_stream([bar], stream, ExpectedVersion.any) + repository.append_to_stream([baz], stream, ExpectedVersion.none) + rescue WrongExpectedEventVersion + end + end + + expect(global_to_a).to eq([foo, bar]) + expect(stream_to_a).to eq([foo, bar]) + end + end + end +end From 055556feb4c0bffb28d79738a69fb4946b124ba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pacana?= Date: Tue, 6 Feb 2024 15:30:07 +0100 Subject: [PATCH 2/3] Make verbose logging optional with VERBOSE=true Co-authored-by: Szymon Fiedler --- ruby_event_store-active_record/spec/transactions_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ruby_event_store-active_record/spec/transactions_spec.rb b/ruby_event_store-active_record/spec/transactions_spec.rb index a6c3f43503..75397f5128 100644 --- a/ruby_event_store-active_record/spec/transactions_spec.rb +++ b/ruby_event_store-active_record/spec/transactions_spec.rb @@ -29,15 +29,17 @@ module ActiveRecord around(:each) { |example| helper.run_lifecycle { example.run } } around(:each) do |example| + previous_logger = ::ActiveRecord::Base.logger ::ActiveRecord::Base.logger = Logger .new(STDOUT) .tap do |l| l.formatter = proc { |severity, datetime, progname, msg| "#{msg}\n" } - end + end if ENV.has_key?("VERBOSE") example.run - ::ActiveRecord::Base.logger = nil + ensure + ::ActiveRecord::Base.logger = previous_logger end specify "no application transaction, event_id conflict" do From 4b198945d3786ee999df0001b659484674ba4856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pacana?= Date: Tue, 6 Feb 2024 15:49:34 +0100 Subject: [PATCH 3/3] One more usage variation Co-authored-by: Szymon Fiedler --- .../spec/transactions_spec.rb | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/ruby_event_store-active_record/spec/transactions_spec.rb b/ruby_event_store-active_record/spec/transactions_spec.rb index 75397f5128..9f89160b89 100644 --- a/ruby_event_store-active_record/spec/transactions_spec.rb +++ b/ruby_event_store-active_record/spec/transactions_spec.rb @@ -94,7 +94,7 @@ module ActiveRecord expect(stream_to_a).to eq([foo]) end - specify "application transaction, event_id conflict — rescued" do + specify "application transaction, event_id conflict — block rescued" do repository.append_to_stream([foo], stream, ExpectedVersion.any) helper.with_transaction do @@ -109,7 +109,7 @@ module ActiveRecord expect(stream_to_a).to eq([foo, bar]) end - specify "application transaction, expected_version conflict — rescued" do + specify "application transaction, expected_version conflict — block rescued" do repository.append_to_stream([foo], stream, ExpectedVersion.none) helper.with_transaction do @@ -123,6 +123,36 @@ module ActiveRecord expect(global_to_a).to eq([foo, bar]) expect(stream_to_a).to eq([foo, bar]) end + + specify "application transaction, event_id conflict — append rescued" do + repository.append_to_stream([foo], stream, ExpectedVersion.any) + + helper.with_transaction do + repository.append_to_stream([bar], stream, ExpectedVersion.any) + begin + repository.append_to_stream([foo], stream, ExpectedVersion.any) + rescue EventDuplicatedInStream + end + end + + expect(global_to_a).to eq([foo, bar]) + expect(stream_to_a).to eq([foo, bar]) + end + + specify "application transaction, expected_version conflict — append rescued" do + repository.append_to_stream([foo], stream, ExpectedVersion.none) + + helper.with_transaction do + repository.append_to_stream([bar], stream, ExpectedVersion.any) + begin + repository.append_to_stream([baz], stream, ExpectedVersion.none) + rescue WrongExpectedEventVersion + end + end + + expect(global_to_a).to eq([foo, bar]) + expect(stream_to_a).to eq([foo, bar]) + end end end end