I've tried using Resque before and was met with unmitigated failure. I'm revisiting it again with the same results...
resque.rake
:
require "resque/tasks"
task "resque:setup" => :environment
test.rb
:
require 'resque'
class FileWorker
@queue = :save_to_file
def self.perform(str)
File.open('./' + Time.now.to_s + '.txt', 'w+') do |f|
f << "test 123"
end
end
end
Resque.enqueue(FileWorker, "12345567".split('').shuffle.join)
Gemfile
:
gem 'resque'
gem 'rake'
It seems like running test.rb
on its own successfully queues the job:
However, running rake resque:work QUEUE='*'
in the same folder results in a warning,
WARNING: This way of doing signal handling is now deprecated. Please see http://hone.heroku.com/resque/2012/08/21/resque-signals.html for more info.
As well as the task being added to "failed" queue with the following reason: "exception":"NameError","error":"uninitialized constant FileWorker"
How do I get this to work? Seems like something quite obvious but there's tons of tutorials about Resque spanning many years - some painfully out of date and none explaining how to run workers so they don't fail.
Thanks in advance.
When you enqueue a task with Resque, what is stored on Redis is just the name of the job class (as a string) along with the arguments (again as strings) in a JSON object.
When a worker then tries to perform the task, it needs to be able to create an instance of the job class. It does this by using const_get
and const_missing
. This is where the error you are seeing occurs, since the worker does not have the definition of FileWorker
available to it.
The error is the same as if you tried to get an unknown constant in irb
:
> Object.const_missing "FileWorker"
NameError: uninitialized constant FileWorker
The solution is to make sure the definition of FileWorker
is available to your workers. The simplest way to do this would be to just require test.rb
from your Rakefile
(or resque.rake
). In your code this would involve adding another task to the queue, so you might want to move the FileWorker
code to its own file where it can be required by both the rake file and the code enqueuing jobs.
test.rb
:
require 'resque'
require './file_worker'
Resque.enqueue(FileWorker, "12345567".split('').shuffle.join)
Rakefile
(note the :environment
task only makes sense if you are using Rails and will give errors otherwise):
require "resque/tasks"
require "./file_worker"
file_worker.rb
:
class FileWorker
@queue = :save_to_file
def self.perform(str)
File.open('./' + Time.now.to_s + '.txt', 'w+') do |f|
f << "test 123"
end
end
end
Now the workers will be able to create instances of FileWorker
to complete the tasks.
The way to avoid the warning about signals is given in the page linked to in the message. Simply set the environment variable TERM_CHILD
when calling rake:
$ rake resque:work QUEUE='*' TERM_CHILD=1