diff --git a/core/lib/spree/event/subscriber_registry.rb b/core/lib/spree/event/subscriber_registry.rb index 1d9572563f5..4e3529e1c01 100644 --- a/core/lib/spree/event/subscriber_registry.rb +++ b/core/lib/spree/event/subscriber_registry.rb @@ -5,10 +5,10 @@ module Event class SubscriberRegistry def initialize @registry = {} + @semaphore = Mutex.new end def register(subscriber) - # thread safe? registry[subscriber.name] ||= {} end @@ -29,26 +29,22 @@ def activate_subscriber(subscriber) return unless registry[subscriber.name] subscriber.event_actions.each do |event_action, event_name| - deactivate_subscriber(subscriber, event_action) + @semaphore.synchronize do + unsafe_deactivate_subscriber(subscriber, event_action) - subscription = Spree::Event.subscribe(event_name) { |event| subscriber.send(event_action, event) } + subscription = Spree::Event.subscribe(event_name) { |event| subscriber.send(event_action, event) } - # deprecated mappings, to be removed when Solidus 2.10 is not supported anymore: - subscriber.send("#{event_action}_handler=", subscription) + # deprecated mappings, to be removed when Solidus 2.10 is not supported anymore: + subscriber.send("#{event_action}_handler=", subscription) - registry[subscriber.name][event_action] = subscription + registry[subscriber.name][event_action] = subscription + end end end - def deactivate_subscriber(subscriber, event_action_name=nil) - to_unsubscribe = Array.wrap(event_action_name || subscriber.event_actions.keys) - - to_unsubscribe.each do |event_action| - if (subscription = registry.dig(subscriber.name, event_action)) - Spree::Event.unsubscribe(subscription) - - registry[subscriber.name].delete(event_action) - end + def deactivate_subscriber(subscriber, event_action_name = nil) + @semaphore.synchronize do + unsafe_deactivate_subscriber(subscriber, event_action_name) end end @@ -79,6 +75,18 @@ def require_subscriber_files Rails.root.glob(pattern) { |c| require_dependency(c.to_s) } end end + + def unsafe_deactivate_subscriber(subscriber, event_action_name = nil) + to_unsubscribe = Array.wrap(event_action_name || subscriber.event_actions.keys) + + to_unsubscribe.each do |event_action| + if (subscription = registry.dig(subscriber.name, event_action)) + Spree::Event.unsubscribe(subscription) + + registry[subscriber.name].delete(event_action) + end + end + end end end end