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 d开发者_如何学Celayed_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]))
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
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.
精彩评论