An action taken by an Observer.
The object to call when the action is triggered.
The minimum number of events that cause the action to be called when the time_threshold is met.
The Hash of recent events, keyed by their arrival time.
The schedule that applies to this action.
The maximum number of seconds between events that cause the action to be called
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
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
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
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
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
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
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