diff --git a/lib/crono/job.rb b/lib/crono/job.rb index 276e373..b77baad 100644 --- a/lib/crono/job.rb +++ b/lib/crono/job.rb @@ -6,18 +6,20 @@ module Crono class Job include Logging - attr_accessor :performer, :period, :last_performed_at, :job_log, - :job_logger, :healthy + attr_accessor :performer, :period, :last_performed_at, + :next_performed_at, :job_log, :job_logger, :healthy def initialize(performer, period) self.performer, self.period = performer, period self.job_log = StringIO.new self.job_logger = Logger.new(job_log) + self.next_performed_at = period.next @semaphore = Mutex.new end def next - period.next(since: last_performed_at) + return next_performed_at if next_performed_at.future? + Time.now end def description @@ -31,6 +33,7 @@ module Crono def perform log "Perform #{performer}" self.last_performed_at = Time.now + self.next_performed_at = period.next(since: last_performed_at) Thread.new { perform_job } end @@ -44,6 +47,7 @@ module Crono def load self.last_performed_at = model.last_performed_at + self.next_performed_at = period.next(since: last_performed_at) end private @@ -61,23 +65,24 @@ module Crono def perform_job performer.new.perform - finished_time_sec = format('%.2f', Time.now - last_performed_at) rescue StandardError => e - handle_job_fail(e, finished_time_sec) + handle_job_fail(e) else - handle_job_success(finished_time_sec) + handle_job_success ensure save end - def handle_job_fail(exception, finished_time_sec) + def handle_job_fail(exception) + finished_time_sec = format('%.2f', Time.now - last_performed_at) self.healthy = false log_error "Finished #{performer} in #{finished_time_sec} seconds"\ - "with error: #{exception.message}" + " with error: #{exception.message}" log_error exception.backtrace.join("\n") end - def handle_job_success(finished_time_sec) + def handle_job_success + finished_time_sec = format('%.2f', Time.now - last_performed_at) self.healthy = true log "Finished #{performer} in #{finished_time_sec} seconds" end diff --git a/spec/scheduler_spec.rb b/spec/scheduler_spec.rb index d1a3ae6..bef9e88 100644 --- a/spec/scheduler_spec.rb +++ b/spec/scheduler_spec.rb @@ -35,16 +35,22 @@ describe Crono::Scheduler do expect(jobs).to be_eql [jobs[0], jobs[1]] end - it 'should return an array of jobs scheduled at same time without `at`' do - time = 5.minutes.from_now + it 'should handle a few jobs scheduled at same time without `at`' do scheduler.jobs = jobs = [ Crono::Period.new(10.seconds), Crono::Period.new(10.seconds), Crono::Period.new(1.day, at: 10.minutes.from_now.strftime('%H:%M')) ].map { |period| Crono::Job.new(TestJob, period) } - time, jobs = scheduler.next_jobs - expect(jobs).to be_eql [jobs[0], jobs[1]] + _, next_jobs = scheduler.next_jobs + expect(next_jobs).to be_eql [jobs[0]] + + Timecop.travel(4.seconds.from_now) + expect(Thread).to receive(:new) + jobs[0].perform + + _, next_jobs = scheduler.next_jobs + expect(next_jobs).to be_eql [jobs[1]] end end end