class BatchKit::Events
Manages batch event notifications and subscriptions, which provide a useful means of decoupling different components of the batch library.
The problem we are looking to solve here is that we want our batch jobs, tasks etc to be able to notify interested parties when something happens (e.g. a task starts, a job fails, etc) without these event sources needing to know all the interested parties to notify. We therefore introduce an intermediary, which is the Events
system.
Interested parties register their interest in specific events or event classes by subscribing to the events of interest. Framework classes then notify the Event system when an event occurs, and the event system routes these notifications on to all registered subscribers.
One of the problems we need to solve for is how subscribers can define the scope of their interest. Is it all events of a particular type, regardless of source? Or are we only interested in events from a specific source (e.g job or task)?
Public Class Methods
Enable/disable event debugging
# File lib/batch-kit/events.rb, line 129 def debug=(dbg) @log = dbg ? LogManager.logger('batch.events') : nil end
Dumps a list of events and their subscribers to the logger
# File lib/batch-kit/events.rb, line 135 def dump_subscribers(show_event = nil, log = @log) if log subscribers.each do |event, subs| if show_event.nil? || show_event == event log.info "Subscribers for event '#{event}':" subs.each{ |sub| log.detail sub.inspect } end end end end
@param source [Object] The source of the event @param event [String] The name of the event @return [Boolean] whether there are any subscribers for the specified
event.
# File lib/batch-kit/events.rb, line 55 def has_subscribers?(source, event) subscribers.has_key?(event) && subscribers[event].size > 0 && subscribers[event].find{ |sub| sub === source } end
Publishes an event to all registered subscribers.
@param source [Object] The source from which the event has been
generated.
@param event [String] The name of the event that has occurred. @param payload [*Object] Arguments
passed with the event.
# File lib/batch-kit/events.rb, line 101 def publish(source, event, *payload) @log.trace "Publishing event '#{event}' for #{source}" if @log res = true count = 0 if subscribers.has_key?(event) subscribers[event].each do |sub| if sub === source begin r = sub.callback.call(source, *payload) count += 1 res &&= r rescue StandardError => ex if sub.raise_on_error raise else STDERR.puts "Exception in '#{event}' event listener for #{source}: #{ex}\n" + " at: #{ex.backtrace[0...10].join("\n")}" end end end end @log.debug "Notified #{count} listeners of '#{event}'" if @log end res end
Setup a subscription for a particular event. When a matching event occurs, the supplied block will be called with the published arguments.
@param source [Object] The type of source object from which to
listen for events.
@param event [String] The name of the event to subscribe to. @param options [Hash] An options hash defining optional settings
for the subscription.
@option options [Fixnum] :position The position within the list to
insert the subscriber. Default is to add to the end of the list.
@param callback [Proc] A block to be invoked when the event occurs.
# File lib/batch-kit/events.rb, line 73 def subscribe(source, event, options = {}, &callback) @log.trace "Adding subscriber for #{source} event '#{event}'" if @log position = options.fetch(:position, -1) if event.is_a?(Array) event.each{ |e| subscribers[e].insert(position, Subscription.new(source, e, options, callback)) } else subscribers[event].insert(position, Subscription.new(source, event, options, callback)) end end
Remove a subscriber
@param source [Object] The object that is the source of the event
from which to unsubscribe.
@param event [String] The name of the event to unsubscribe from.
# File lib/batch-kit/events.rb, line 89 def unsubscribe(source, event) @log.trace "Removing subscriber(s) for #{source} event '#{event}'" if @log subscribers[event].delete_if{ |sub| sub === source } end
Private Class Methods
# File lib/batch-kit/events.rb, line 149 def subscribers @subscribers ||= Hash.new{ |h, k| h[k] = [] } end