Question

I'm using the delayed_job plugin in Rails to do background processing, and I'm experiencing a hiccup in the 'agile development' I've been experiencing so far in Rails...

Usually in rails if I hit an error / want to add some new functionality - I just add some code and refresh the page and the new code runs.

With delayed_job, it seems like the job class isn't being reloaded... if a job fails and I go and fix the error and fire the job again, the old code runs again.

Is there any way to make delayed_job load the newest version of the job class before invoking it?

Just in case this has anything to do with it - I know delayed_job has a few different options in the ways to declare jobs / run jobs:

My job class is in the lib directory of Rails and is declared like:

class FooJob < Struct.new(:foo_id)

and I'm invoking the job like this from the controller:

Delayed::Job.enqueue(FooJob.new(params[:id]))
Was it helpful?

Solution

There is nothing builtin to do this. Generally you are responsible for managing and reloading your workers. This is probably just as well since Rails development reloading is good but not perfect, and attempting to auto-reload a delayed job would potentially run into all sort subtle issues that would be pretty opaque to debug inside a worker process. Also, if it automatically reloaded the environment for every job a lot of use cases would get tremendously slow in dev mode.

My suggestion is just to get use to doing rake jobs:work and then Ctrl-C when you make changes. Alternatively you can create a script that just manually runs the jobs on an ad-hoc basis (taken from delayed_job docs):

#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/environment'

Delayed::Worker.new.start  

OTHER TIPS

I use this hack that seams to work quite nice, but be aware that it's probably very Rails and delayed_job version specific so you probably need to change some things. Tested with Rails 3.2.0 and delayed_job 2.1.4.

Put this into e.g. script/delayed_job_development and run it from the Rails root.

#!/usr/bin/env ruby

require File.expand_path('../config/environment', File.dirname(__FILE__))
require 'delayed/worker'
require "rails/console/app"

class DummyConsoleClass
  include Rails::ConsoleMethods
end
dummy_console = DummyConsoleClass.new

worker = Delayed::Worker.new({:quiet => false})

puts "Waiting for jobs..."
loop do
  if Delayed::Job.find_available(worker.name).count > 0
    puts "Found jobs"
    dummy_console.reload!
    loop do
      break if worker.work_off.sum == 0
    end
    puts "Done, waiting for jobs..."
  end
  sleep(2)
end

Please comment if you know that this is a very bad idea or things to be aware of, I mainly use it when editing and testing jobs that run immediately not with jobs scheduled to run long into the future.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top