lib/reactor/models/concerns/subscribable.rb in reactor-0.10.1 vs lib/reactor/models/concerns/subscribable.rb in reactor-0.11.0

- old
+ new

@@ -1,27 +1,40 @@ module Reactor::Subscribable extend ActiveSupport::Concern + class EventHandlerAlreadyDefined < StandardError ; end + module ClassMethods def on_event(*args, &block) options = args.extract_options! event, method = args - (Reactor::SUBSCRIBERS[event.to_s] ||= []).push(StaticSubscriberFactory.create(event, method, {source: self}.merge(options), &block)) + (Reactor::SUBSCRIBERS[event.to_s] ||= []).push(create_static_subscriber(event, method, options, &block)) end - end - class StaticSubscriberFactory + private - def self.create(event, method = nil, options = {}, &block) - handler_class_prefix = event == '*' ? 'Wildcard': event.to_s.camelize - i = 0 - begin - new_class = "#{handler_class_prefix}Handler#{i}" - i+= 1 - end while Reactor::StaticSubscribers.const_defined?(new_class) + def create_static_subscriber(event, method = nil, options = {}, &block) + worker_class = build_worker_class - klass = Class.new do + name_worker_class worker_class, handler_name(event, options[:handler_name]) + + worker_class.tap do |k| + k.source = self + k.method = method || block + k.delay = options[:delay] || 0 + k.in_memory = options[:in_memory] + k.dont_perform = Reactor.test_mode? + end + end + + def handler_name(event, handler_name_option = nil) + return handler_name_option.to_s.camelize if handler_name_option + "#{event == '*' ? 'Wildcard': event.to_s.camelize}Handler" + end + + def build_worker_class + Class.new do include Sidekiq::Worker class_attribute :method, :delay, :source, :in_memory, :dont_perform def perform(data) @@ -40,18 +53,26 @@ else perform_async(data) end end end + end - Reactor::StaticSubscribers.const_set(new_class, klass) + def name_worker_class(klass, handler_name) + if static_subscriber_namespace.const_defined?(handler_name) + raise EventHandlerAlreadyDefined.new( + "A Reactor event named #{handler_name} already has been defined on #{static_subscriber_namespace}. + Specify a `:handler_name` option on your subscriber's `on_event` declaration to name this event handler deterministically." + ) + end + static_subscriber_namespace.const_set(handler_name, klass) + end - klass.tap do |k| - k.method = method || block - k.delay = options[:delay] || 0 - k.source = options[:source] - k.in_memory = options[:in_memory] - k.dont_perform = Reactor.test_mode? + def static_subscriber_namespace + unless Reactor::StaticSubscribers.const_defined?(self.name, false) + Reactor::StaticSubscribers.const_set(self.name, Module.new) end + + Reactor::StaticSubscribers.const_get(self.name, false) end end end