classRufus::Scheduler::RepeatJob<Rufus::Scheduler::Jobattr_reader:paused_atattr_reader:first_atattr_reader:last_atattr_accessor:timesdefinitialize(scheduler,duration,opts,block)super@paused_at=nil@times=opts[:times]failArgumentError.new("cannot accept :times => #{@times.inspect}, not nil or an int")unless@times==nil||@times.is_a?(Integer)self.first_at=opts[:first]||opts[:first_time]||opts[:first_at]||opts[:first_in]||nilself.last_at=opts[:last]||opts[:last_at]||opts[:last_in]@resume_discard_past=nilendFIRSTS=[:now,:immediately,0].freezedeffirst_at=(first)return(@first_at=nil)iffirst==niln0=EoTime.nown1=n0+0.003first=n0ifFIRSTS.include?(first)fdur=Rufus::Scheduler.parse_duration(first,no_error: true)@first_at=(fdur&&(EoTime.now+fdur))||EoTime.make(first)@first_at=n1if@first_at>=n0&&@first_at<n1failArgumentError.new("cannot set first[_at|_in] in the past: "+"#{first.inspect} -> #{@first_at.inspect}")if@first_at<n0@first_atenddeflast_at=(last)@last_at=iflastldur=Rufus::Scheduler.parse_duration(last,no_error: true)(ldur&&(EoTime.now+ldur))||EoTime.make(last)elsenilendfailArgumentError.new("cannot set last[_at|_in] in the past: "+"#{last.inspect} -> #{@last_at.inspect}")iflast&&@last_at<EoTime.now@last_atenddeftrigger(time)returnif@paused_at#return set_next_time(time) if @paused_atreturn(@next_time=nil)if@times&&@times<1return(@next_time=nil)if@last_at&&time>=@last_at## It keeps jobs one step too much in @jobs, but it's OKsuper@times-=1if@timesenddefpause@paused_at=EoTime.nowenddefresume(opts={})@resume_discard_past=opts[:discard_past]@paused_at=nilenddefpaused?!!@paused_atenddefdetermine_id[self.class.name.split(':').last.downcase[0..-4],@scheduled_at.to_f,(self.object_id<0?'m':'')+self.object_id.to_s].map(&:to_s).join('_')enddefoccurrences(time0,time1)a=[]nt=@next_timets=@timesloopdobreakifnt>time1breakifts&&ts<=0a<<ntifnt>=time0nt=next_time_from(nt)ts=ts-1iftsendaend# Starting from now, returns the {count} next occurences# (EtOrbi::EoTime instances) for this job.## Warning, for IntervalJob, the @mean_work_time is used since# "interval" works from the end of a job to its next trigger# (not from one trigger to the next, as for "cron" and "every").#defnext_times(count)(count-1).times.inject([next_time]){|a|a<<next_time_from(a.last)a}endend## A parent class of EveryJob and IntervalJob#classRufus::Scheduler::EvInJob<Rufus::Scheduler::RepeatJobdeffirst_at=(first)@next_time=superendendclassRufus::Scheduler::EveryJob<Rufus::Scheduler::EvInJobattr_reader:frequencyattr_accessor:resume_discard_pastdefinitialize(scheduler,duration,opts,block)super(scheduler,duration,opts,block)@frequency=Rufus::Scheduler.parse_in(@original)failArgumentError.new("cannot schedule #{self.class} with a frequency "+"of #{@frequency.inspect} (#{@original.inspect})")if@frequency<=0set_next_time(nil)enddefcheck_frequencyfailArgumentError.new("job frequency (#{@frequency}s) is higher than "+"scheduler frequency (#{@scheduler.frequency}s)")if@frequency<@scheduler.frequencyenddefnext_time_from(time)time+@frequencyendprotecteddefset_next_time(trigger_time,is_post=false,now=nil)returnifis_postn=now||EoTime.nowreturn@next_time=@first_at\if@first_at&&(trigger_time==nil||@first_at>n)dp=discard_past?loopdo@next_time=(@next_time||n)+@frequencybreakifdp==falsebreakif@next_time>nendendendclassRufus::Scheduler::IntervalJob<Rufus::Scheduler::EvInJobattr_reader:intervaldefinitialize(scheduler,interval,opts,block)super(scheduler,interval,opts,block)@interval=Rufus::Scheduler.parse_in(@original)failArgumentError.new("cannot schedule #{self.class} with an interval "+"of #{@interval.inspect} (#{@original.inspect})")if@interval<=0set_next_time(nil)enddefnext_time_from(time)time+@mean_work_time+@intervalendprotecteddefset_next_time(trigger_time,is_post=false,now=nil)n=now||EoTime.now@next_time=ifis_postn+@intervalelsiftrigger_time.nil?if@first_at==nil||@first_at<nn+@intervalelse@first_atendelsefalseendendendclassRufus::Scheduler::CronJob<Rufus::Scheduler::RepeatJobattr_reader:cron_linedefinitialize(scheduler,cronline,opts,block)super(scheduler,cronline,opts,block)@cron_line=opts[:_t]||::Fugit::Cron.do_parse(cronline)set_next_time(nil)enddefcheck_frequencyreturnif@scheduler.frequency<=1## The minimum time delta in a cron job is 1 second, so if the# scheduler frequency is less than that, no worries.f=@cron_line.rough_frequencyfailArgumentError.new("job frequency (min ~#{f}s) is higher than "+"scheduler frequency (#{@scheduler.frequency}s)")iff<@scheduler.frequencyenddefbrute_frequency@cron_line.brute_frequencyenddefrough_frequency@cron_line.rough_frequencyenddefnext_time_from(time)@cron_line.next_time(time)endprotecteddefset_next_time(trigger_time,is_post=false,now=nil)returnifis_postt=trigger_time||now||EoTime.nowprevious=@previous_time||@scheduled_att=previousif!discard_past?&&t>previous@next_time=if@first_at&&@first_at>t@first_atelse@cron_line.next_time(t)endendend