Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kjwierenga/112478 to your computer and use it in GitHub Desktop.
Save kjwierenga/112478 to your computer and use it in GitHub Desktop.
def schedule_event(event)
now = Time.now
# Determine the next occurrence starting at (Time.now - event.duration) to
# catch the current occurence where start_at <= Time.now but end_at > Time.now.
#
# When occurrence == nil, this means the event will never occur.
occurrence = event.occurrences(:starting => now - event.duration, :count => 1)
return if occurrence.nil?
# Determine trigger time and end time.
# Note that occurrence.dtend still has the original value of event.end_at
# which may be in the past.
# TODO: Is this a ri_cal bug?
trigger_at = occurrence.dtstart.to_time + event.trigger*60
end_at = occurrence.dtstart.to_time + event.duration
# Trigger the event immediately when Time.now falls within the timerange of the event.
# Set trigger_at to now to ensure correct job.at value in #schedule_next_occurrence.
if trigger_immediately = (trigger_at <= now && now < end_at)
trigger_at = now
end
@scheduler.at(trigger_at,
:job_id => event.id,
:tags => 'event',
:discard_past => !trigger_immediately,
:event => event,
:sequence => 0) do |job|
sequence = job.params[:sequence]
schedule_next_occurrence(job) unless "SINGLE" == event.recurrence
# do the stuff (start remote recording)
# sleep event.duration
end
end
def schedule_next_occurrence(job)
event = job.params[:event]
# find next occurrence after the current occurrence
return unless occurrence = event.occurrences(:starting => Time.at(job.at), :count => 1)
job.params[:discard_past] = false # should not fire immediately (would cause a loop)
job.params[:sequence] += 1
# reschedule the job by setting a new @at value and adding to the job queue again
job.instance_variable_set('@at', (occurrence.dtstart.to_time + event.trigger*60).to_f)
@scheduler.send(:add_job, job)
end
#
# Relevant details of the Event class
#
class Event
attr_accessor :start_at, :end_at, :rrule
def duration; end_at - start_at; end
#
# Use RiCal::OccurrenceEnumerator#occurrences to return the next :count occurrence
# for the event between :starting and :before
#
def occurrences(options = {})
occurrences = []
enum_event = RiCal.Event do |event|
event.dtstart = self.start_at.utc
event.dtend = self.end_at.utc
event.rrule = self.rrule
end
occurrences = [enum_event]
occurrences = [] if options[:starting] && self.start_at < options[:starting]
occurrences = [] if options[:before] && self.start_at >= options[:before]
(options[:count].nil? || options[:count] > 1 ? occurrences : occurrences.first)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment