diff --git a/.ruby-version b/.ruby-version index be94e6f53..b347b11ea 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.2 +3.2.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cc794df6..fd653fa34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 1.4.3 - 2024-05-06 +### Changed +- The order of execution for synchronous reactors is now guaranteed to be the order in which they were registered. +- The shared examples for reactors `'an event which (a)synchronously dispatches'` now accept 1 or multiple arguments. The synchronous version checks that reactors are given in the order in which they are registered. + ## 1.4.2 - 2024-04-30 ### Changed - Raise error on missing consumer config diff --git a/Gemfile.lock b/Gemfile.lock index d32aaf937..07b61b238 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - eventsimple (1.4.2) + eventsimple (1.4.3) dry-struct (~> 1.6) dry-types (~> 1.7) pg (~> 1.4) diff --git a/lib/eventsimple/event_dispatcher.rb b/lib/eventsimple/event_dispatcher.rb index 2494d81a0..587f4a129 100644 --- a/lib/eventsimple/event_dispatcher.rb +++ b/lib/eventsimple/event_dispatcher.rb @@ -55,6 +55,7 @@ def register(events:, sync:, async:) end # Return a ReactorSet containing all Reactors matching an Event + # Reactors will be in the order in which they were registered def for(event) reactors = ReactorSet.new @@ -77,16 +78,16 @@ class ReactorSet attr_reader :sync, :async def initialize - @sync = Set.new - @async = Set.new + @sync = [] + @async = [] end def add_sync(reactors) - @sync += reactors + @sync |= reactors end def add_async(reactors) - @async += reactors + @async |= reactors end end end diff --git a/lib/eventsimple/support/spec_helpers.rb b/lib/eventsimple/support/spec_helpers.rb index 5b7f97eea..e5498534c 100644 --- a/lib/eventsimple/support/spec_helpers.rb +++ b/lib/eventsimple/support/spec_helpers.rb @@ -1,18 +1,20 @@ # frozen_string_literal: true -RSpec.shared_examples 'an event which synchronously dispatches' do |dispatcher_klass| +RSpec.shared_examples 'an event which synchronously dispatches' do |*dispatcher_klasses| specify do reactors = Eventsimple::EventDispatcher.rules.for(described_class.new) - expect(reactors.sync).to include(dispatcher_klass) + # Order is important here since the synchronous reactors are executed sequentially + expect(reactors.sync & dispatcher_klasses).to eq(dispatcher_klasses) end end -RSpec.shared_examples 'an event which asynchronously dispatches' do |dispatcher_klass| +RSpec.shared_examples 'an event which asynchronously dispatches' do |*dispatcher_klasses| specify do reactors = Eventsimple::EventDispatcher.rules.for(described_class.new) - expect(reactors.async).to include(dispatcher_klass) + # Order is _not_ important here since async reactors have no order guarantee + expect(reactors.async).to include(*dispatcher_klasses) end end diff --git a/lib/eventsimple/version.rb b/lib/eventsimple/version.rb index a49b55ea8..a59114528 100644 --- a/lib/eventsimple/version.rb +++ b/lib/eventsimple/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Eventsimple - VERSION = '1.4.2' + VERSION = '1.4.3' end diff --git a/spec/dummy/app/components/user_component/dispatcher.rb b/spec/dummy/app/components/user_component/dispatcher.rb index fc298782f..9895ccecd 100644 --- a/spec/dummy/app/components/user_component/dispatcher.rb +++ b/spec/dummy/app/components/user_component/dispatcher.rb @@ -1,6 +1,13 @@ module UserComponent class Dispatcher < Eventsimple::Dispatcher - on Events::Created, sync: Reactors::Created::SyncReactor + on( + Events::Created, + sync: [ + Reactors::Created::SyncReactor, + Reactors::Created::SyncReactor2, + ], + async: Reactors::Created::AsyncReactor2, + ) on Events::RescuedInvalidTransition, sync: Reactors::Created::SyncReactor on Events::RescuedInvalidTransitionWithReraise, sync: Reactors::Created::SyncReactor diff --git a/spec/dummy/app/components/user_component/reactors/created/async_reactor_2.rb b/spec/dummy/app/components/user_component/reactors/created/async_reactor_2.rb new file mode 100644 index 000000000..bcb402c80 --- /dev/null +++ b/spec/dummy/app/components/user_component/reactors/created/async_reactor_2.rb @@ -0,0 +1,10 @@ +module UserComponent + module Reactors + module Created + class AsyncReactor2 < Eventsimple::Reactor + def call(event) + end + end + end + end +end diff --git a/spec/dummy/app/components/user_component/reactors/created/sync_reactor_2.rb b/spec/dummy/app/components/user_component/reactors/created/sync_reactor_2.rb new file mode 100644 index 000000000..2e1472d39 --- /dev/null +++ b/spec/dummy/app/components/user_component/reactors/created/sync_reactor_2.rb @@ -0,0 +1,10 @@ +module UserComponent + module Reactors + module Created + class SyncReactor2 < Eventsimple::Reactor + def call(event) + end + end + end + end +end diff --git a/spec/dummy/spec/components/user_component/events/created_spec.rb b/spec/dummy/spec/components/user_component/events/created_spec.rb index 553b6cb0f..46ebbc397 100644 --- a/spec/dummy/spec/components/user_component/events/created_spec.rb +++ b/spec/dummy/spec/components/user_component/events/created_spec.rb @@ -21,6 +21,10 @@ it_behaves_like 'an event which synchronously dispatches', UserComponent::Reactors::Created::SyncReactor + it_behaves_like 'an event which synchronously dispatches', + UserComponent::Reactors::Created::SyncReactor, + UserComponent::Reactors::Created::SyncReactor2 + it 'updates the user properties' do create_event diff --git a/spec/lib/eventsimple/event_dispatcher_spec.rb b/spec/lib/eventsimple/event_dispatcher_spec.rb index 987610c55..2273092cc 100644 --- a/spec/lib/eventsimple/event_dispatcher_spec.rb +++ b/spec/lib/eventsimple/event_dispatcher_spec.rb @@ -29,5 +29,25 @@ module Eventsimple ).with(event).at(:no_wait) end end + + describe '.rules' do + describe '#for' do + it 'returns the sync reactors in the order in which they were registered' do + expected_reactors = [ + UserComponent::Reactors::Created::SyncReactor, + UserComponent::Reactors::Created::SyncReactor2, + ] + expect(described_class.rules.for(UserComponent::Events::Created.new).sync).to eq expected_reactors + end + + it 'returns the async reactors in the order in which they were registered' do + expected_reactors = [ + UserComponent::Reactors::Created::AsyncReactor2, + UserComponent::Reactors::Created::AsyncReactor, + ] + expect(described_class.rules.for(UserComponent::Events::Created.new).async).to eq expected_reactors + end + end + end end end