summaryrefslogtreecommitdiff
path: root/app/services/job_scheduler.rb
blob: 01c9bdbcc84aed20061eb1d2a4582c5eccf37ded (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class JobScheduler

  attr_reader :ident
  def initialize(ident = nil)
    @ident = ident
  end

  def start_work!
    while run_next_job
    end
  end

  private
  def run_next_job
    ActiveRecord::Base.transaction do
      job = dequeue_job!

      unless job
        Rails.logger.info "Nothing to do."
        return false
      end

      log = JobLog.new(job: job, scheduler: ident)

      # Note that we may want to trade full consistency over
      # making sure the database transactions are short.
      #
      # We could reschedule the job here and commit
      # and only then execute the job.

      begin
        JobWorker.new(job).perform
      ensure
        log.save!
        reschedule(job)
      end

      return true
    end
  end

  def dequeue_job!
    Job.lock('FOR UPDATE SKIP LOCKED').where('scheduled_for <= NOW()').order(:scheduled_for, :id).limit(1).first
  end

  def reschedule(job)
    job.scheduled_for = Time.now() + 10.seconds
    job.save!
  end
end