Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delayed_Job: accessing job metadata and/or avoiding duplicate jobs

i'm trying to get the run_at datetime in a custom job class. my code looks like this:

class MyCustomJob < Struct.new(:my_object)

  def perform
    if self.run_at == my_object.start_time
      # process the job
    end
  end

end

i also tried a Delayed::Job.find(self) but had no luck.

thanks in advance

like image 352
Oliver Avatar asked Jul 27 '11 14:07

Oliver


2 Answers

If you define a before method on your custom job, the worker will pass you the delayed job instance before calling perform:

class MyCustomTask

  def before(job)
    @job = job
  end

  def perform
    # has access to @job object. 
    # You may need to call @job.reload to see in-flight changes to object in the database.
  end
end
like image 77
nicsnoek Avatar answered Oct 30 '22 14:10

nicsnoek


You should handle this when you create the job:

   priority = 0
   run_time = my_object.start_time
   Delayed::Job.enqueue(MyCustomJob.new(my_object), priority, run_time)

https://github.com/tobi/delayed_job/wiki

If your jobs aren't running at the expected time, you may be scheduling them for UTC:

http://www.gregbenedict.com/2009/08/19/is-delayed-job-run_at-datetime-giving-you-fits/

To check the queue for an existing job - you could do the following:


class MyCustomJob < Struct.new(:object_id)

  def self.exists?(object_id)
    Delayed::Job.where(['handler = ? and failed_at is null',handler(object_id)]).count(:all) > 0
  end

  def self.handler(object_id)
    "--- !ruby/struct:MyCustomJob \nobject_id: #{object_id}\n"
  end

  def perform
    my_object = MyObject.find(object_id)
    my_object.do_stuff
  end
end

Then just check for MyCustomJob.exists?(my_object.id) before queueing.

It's a little bit of a hack - edit the handler method as needed. I would modify the delayed_jobs table to have a class/object_id to make for cleaner code and more efficient table scans if your jobs table is large or if you do this with other types of jobs.

This question also looks relevant:

How to cancel scheduled job with delayed_job in Rails?

like image 45
klochner Avatar answered Oct 30 '22 12:10

klochner