3
votes

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:

enter image description here

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.

1
This SomeWork constant that is missing. Where is it? Seems to me that you are missing to require something when running it with rake (stuff that is included by default when testing perhaps?). - froderik
I can't see SomeWork in any of the code you posted - post the real code. - simonwo
Whether I require it SomeWork or not (in the rakefile), it still seems that it's missing when push comes to shove with resque - dsp_099
There's so much that can go wrong, I wish I could help directly. Unfortunately my own experience with Resque is limited to a single project I did as a student. This may not be helpful, but have you checked out the excellent RailsCasts episode on Resque? railscasts.com/episodes/271-resque - pgblu
Do you have the Resque.enqueue command only in your test.rb file? You need to [also] have it in your controller, or wherever else you want to initiate the worker. Oh, and the warning is not relevant to the problem... not that it doesn't matter but alleviating the warning won't solve your problem, and ignoring it won't prevent your problem from being solved. - pgblu

1 Answers

9
votes

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