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

debug=(dbg) click to toggle source

Enable/disable event debugging

# File lib/batch-kit/events.rb, line 129
def debug=(dbg)
    @log = dbg ? LogManager.logger('batch.events') : nil
end
dump_subscribers(show_event = nil, log = @log) click to toggle source

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
has_subscribers?(source, event) click to toggle source

@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
publish(source, event, *payload) click to toggle source

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
subscribe(source, event, options = {}, &callback) click to toggle source

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
unsubscribe(source, event) click to toggle source

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

subscribers() click to toggle source
# File lib/batch-kit/events.rb, line 149
def subscribers
    @subscribers ||= Hash.new{ |h, k| h[k] = [] }
end