class Symphony::Metronome::ScheduledEvent
A class the represents the relationship between an interval and an event.
Constants
- CONFIG_DEFAULTS
Configure defaults.
Attributes
A Sequel-style DB connection URI.
Adjust recurring intervals by a random window.
The sequel dataset representing this event.
The parsed interval expression.
The unique ID number of the scheduled event.
The options hash attached to this event.
The exact time that this event will run.
Public Class Methods
Configurability API.
# File lib/symphony/metronome/scheduledevent.rb, line 46 def self::configure( config=nil ) config = self.defaults.merge( config || {} ) @db = Sequel.connect( config.delete(:db) ) @splay = config.delete( :splay ) # Ensure the database is current. # migrations_dir = Symphony::Metronome::DATADIR + 'migrations' unless Sequel::Migrator.is_current?( self.db, migrations_dir.to_s ) Loggability[ Symphony ].info "Installing database schema..." Sequel::Migrator.apply( self.db, migrations_dir.to_s ) end end
Return a set of all known events, sorted by date of execution. Delete any rows that are invalid expressions.
# File lib/symphony/metronome/scheduledevent.rb, line 64 def self::load now = Time.now events = SortedSet.new # Force reset the DB handle. self.db.disconnect self.log.debug "Parsing/loading all actions." self.db[ :metronome ].each do |event| begin event = new( event ) events << event rescue ArgumentError, Symphony::Metronome::TimeParseError => err self.log.error "%p while parsing \"%s\": %s" % [ err.class, event[:expression], err.message ] self.log.debug " " + err.backtrace.join( "\n " ) self.db[ :metronome ].filter( :id => event[:id] ).delete end end return events end
Create a new ScheduledEvent
object.
# File lib/symphony/metronome/scheduledevent.rb, line 97 def initialize( row ) @event = Symphony::Metronome::IntervalExpression.parse( row[:expression], row[:created] ) @options = row.delete( :options ) @id = row.delete( :id ) @ds = self.class.db[ :metronome ].filter( :id => self.id ) self.reset_runtime unless self.class.splay.zero? splay = Range.new( - self.class.splay, self.class.splay ) @runtime = self.runtime + rand( splay ) end end
Public Instance Methods
Comparable interface, order by next run time, soonest first.
# File lib/symphony/metronome/scheduledevent.rb, line 212 def <=>( other ) return self.runtime <=> other.runtime end
Permanently remove this event from the database.
# File lib/symphony/metronome/scheduledevent.rb, line 204 def delete self.log.debug "Removing action %p" % [ self.id ] self.ds.delete end
Perform the action attached to the event. Yields the deserialized options, the action ID to the supplied block if this event is okay to execute.
If the event is recurring, perform additional checks against the last run time.
Automatically remove the event if it has expired.
# File lib/symphony/metronome/scheduledevent.rb, line 169 def fire rv = self.event.fire? # Just based on the expression parser, is this event ready to fire? # if rv opts = Yajl.load( self.options ) # Don't fire recurring events unless their interval has elapsed. # This prevents events from triggering when the daemon receives # a HUP. # if self.event.recurring now = Time.now row = self.ds.first if row last = row[ :lastrun ] return false if last && now - last < self.event.interval end # Mark the time this recurring event was fired. self.ds.update( :lastrun => Time.now ) end yield opts, self.id end self.delete if rv.nil? return rv end
Set the datetime that this event should fire next.
# File lib/symphony/metronome/scheduledevent.rb, line 129 def reset_runtime now = Time.now # Start time is in the future, so it's sufficent to be considered the run time. # if self.event.starting >= now @runtime = self.event.starting return end # Otherwise, the event should already be running (start time has already # elapsed), so schedule it forward on it's next interval iteration. # # If it's a recurring event that has run before, consider the elapsed time # as part of the next calculation. # row = self.ds.first if self.event.recurring && row last = row[ :lastrun ] if last && now > last @runtime = now + self.event.interval - ( now - last ) else @runtime = now + self.event.interval end else @runtime = now + self.event.interval end end