Action

class
Superclass
Object
Extended With
Loggability

An action taken by an Observer.

Attributes

block[R]

The object to call when the action is triggered.

count_threshold[R]

The minimum number of events that cause the action to be called when the time_threshold is met.

event_history[R]

The Hash of recent events, keyed by their arrival time.

schedule[R]

The schedule that applies to this action.

time_threshold[R]

The maximum number of seconds between events that cause the action to be called

Public Class Methods

anchor
new( within: 0, after: 1, during: nil, &block )

Create a new Action that will call the specified block during the given schedule, but only after the specified number of events have arrived within the given time threshold.

# File lib/arborist/observer/action.rb, line 21
def initialize( within: 0, after: 1, during: nil, &block )
        raise ArgumentError, "Action requires a block" unless block

        @block           = block
        @time_threshold  = within
        @schedule        = Schedulability::Schedule.parse( during ) if during

        if within.zero?
                @count_threshold = after
        else
                # It should always be 2 or more if there is a time threshold
                @count_threshold = [ after, 2 ].max
        end

        @event_history = {}
end

Public Instance Methods

anchor
call_block( event )

Execute the action block with the specified event.

# File lib/arborist/observer/action.rb, line 74
def call_block( event )
        if self.block.arity >= 2 || self.block.arity < 0
                self.block.call( event.dup, self.event_history.dup )
        else
                self.block.call( event.dup )
        end
rescue => err
        self.log.error "Exception while running observer: %s: %s\n%s" % [
                err.class.name,
                err.message,
                err.backtrace.join("\n  ")
        ]
ensure
        self.event_history.clear
end
anchor
count_threshold_exceeded?()

Returns true if the number of events in the event history meet or exceed the count_threshold.

# File lib/arborist/observer/action.rb, line 126
def count_threshold_exceeded?
        return self.event_history.size >= self.count_threshold
end
anchor
handle_event( event )

Call the action for the specified event.

# File lib/arborist/observer/action.rb, line 66
def handle_event( event )
        self.record_event( event )
        self.call_block( event ) if self.should_run?
end
anchor
record_event( event )

Record the specified event in the event history if within the scheduled period(s).

# File lib/arborist/observer/action.rb, line 92
def record_event( event )
        return if self.schedule && !self.schedule.now?
        self.event_history[ Time.now ] = event
        self.event_history.keys.sort.each do |event_time|
                break if self.event_history.size <= self.count_threshold
                self.event_history.delete( event_time )
        end
end
anchor
should_run?()

Returns true if the threshold is exceeded and the current time is within the action's schedule.

# File lib/arborist/observer/action.rb, line 104
def should_run?
        return self.time_threshold_exceeded? && self.count_threshold_exceeded?
end
anchor
time_threshold_exceeded?()

Returns true if the time between the first and last event in the event_history is less than the time_threshold.

# File lib/arborist/observer/action.rb, line 111
def time_threshold_exceeded?
        return true if self.time_threshold.zero?
        return false unless self.count_threshold_exceeded?

        first = self.event_history.keys.min
        last = self.event_history.keys.max

        self.log.debug "Time between the %d events in the record (%p): %0.5fs" %
                [ self.event_history.size, self.event_history, last - first ]
        return last - first <= self.time_threshold
end