mirror of
https://github.com/plashchynski/crono.git
synced 2026-05-07 08:24:11 +02:00
Handle a few jobs scheduled at the same time
This commit is contained in:
@@ -6,18 +6,20 @@ module Crono
|
|||||||
class Job
|
class Job
|
||||||
include Logging
|
include Logging
|
||||||
|
|
||||||
attr_accessor :performer, :period, :last_performed_at, :job_log,
|
attr_accessor :performer, :period, :last_performed_at,
|
||||||
:job_logger, :healthy
|
:next_performed_at, :job_log, :job_logger, :healthy
|
||||||
|
|
||||||
def initialize(performer, period)
|
def initialize(performer, period)
|
||||||
self.performer, self.period = performer, period
|
self.performer, self.period = performer, period
|
||||||
self.job_log = StringIO.new
|
self.job_log = StringIO.new
|
||||||
self.job_logger = Logger.new(job_log)
|
self.job_logger = Logger.new(job_log)
|
||||||
|
self.next_performed_at = period.next
|
||||||
@semaphore = Mutex.new
|
@semaphore = Mutex.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def next
|
def next
|
||||||
period.next(since: last_performed_at)
|
return next_performed_at if next_performed_at.future?
|
||||||
|
Time.now
|
||||||
end
|
end
|
||||||
|
|
||||||
def description
|
def description
|
||||||
@@ -31,6 +33,7 @@ module Crono
|
|||||||
def perform
|
def perform
|
||||||
log "Perform #{performer}"
|
log "Perform #{performer}"
|
||||||
self.last_performed_at = Time.now
|
self.last_performed_at = Time.now
|
||||||
|
self.next_performed_at = period.next(since: last_performed_at)
|
||||||
|
|
||||||
Thread.new { perform_job }
|
Thread.new { perform_job }
|
||||||
end
|
end
|
||||||
@@ -44,6 +47,7 @@ module Crono
|
|||||||
|
|
||||||
def load
|
def load
|
||||||
self.last_performed_at = model.last_performed_at
|
self.last_performed_at = model.last_performed_at
|
||||||
|
self.next_performed_at = period.next(since: last_performed_at)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -61,23 +65,24 @@ module Crono
|
|||||||
|
|
||||||
def perform_job
|
def perform_job
|
||||||
performer.new.perform
|
performer.new.perform
|
||||||
finished_time_sec = format('%.2f', Time.now - last_performed_at)
|
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
handle_job_fail(e, finished_time_sec)
|
handle_job_fail(e)
|
||||||
else
|
else
|
||||||
handle_job_success(finished_time_sec)
|
handle_job_success
|
||||||
ensure
|
ensure
|
||||||
save
|
save
|
||||||
end
|
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
|
self.healthy = false
|
||||||
log_error "Finished #{performer} in #{finished_time_sec} seconds"\
|
log_error "Finished #{performer} in #{finished_time_sec} seconds"\
|
||||||
"with error: #{exception.message}"
|
" with error: #{exception.message}"
|
||||||
log_error exception.backtrace.join("\n")
|
log_error exception.backtrace.join("\n")
|
||||||
end
|
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
|
self.healthy = true
|
||||||
log "Finished #{performer} in #{finished_time_sec} seconds"
|
log "Finished #{performer} in #{finished_time_sec} seconds"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,16 +35,22 @@ describe Crono::Scheduler do
|
|||||||
expect(jobs).to be_eql [jobs[0], jobs[1]]
|
expect(jobs).to be_eql [jobs[0], jobs[1]]
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return an array of jobs scheduled at same time without `at`' do
|
it 'should handle a few jobs scheduled at same time without `at`' do
|
||||||
time = 5.minutes.from_now
|
|
||||||
scheduler.jobs = jobs = [
|
scheduler.jobs = jobs = [
|
||||||
Crono::Period.new(10.seconds),
|
Crono::Period.new(10.seconds),
|
||||||
Crono::Period.new(10.seconds),
|
Crono::Period.new(10.seconds),
|
||||||
Crono::Period.new(1.day, at: 10.minutes.from_now.strftime('%H:%M'))
|
Crono::Period.new(1.day, at: 10.minutes.from_now.strftime('%H:%M'))
|
||||||
].map { |period| Crono::Job.new(TestJob, period) }
|
].map { |period| Crono::Job.new(TestJob, period) }
|
||||||
|
|
||||||
time, jobs = scheduler.next_jobs
|
_, next_jobs = scheduler.next_jobs
|
||||||
expect(jobs).to be_eql [jobs[0], jobs[1]]
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user