Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't my resque job find the object?

In our Rails app. We save a model (Video). We have a callback on that object:

after_create :send_to_background_job, :if => :persisted?

The method looks like:

def send_to_background_job
  Resque.enqueue(AddVideo, self.id)
end

When the worker is called. It does the following:

class AddVideo
  @queue = :high

  def self.perform(video_id)
    video = Video.find(video_id)
    video.original_file_name
    ....

Resque-web reports an error:

AddVideo
Arguments
51061
Exception
NoMethodError
Error
undefined method `original_filename' for nil:NilClass

Which is a bit odd, because, if I go to Rails console to look for this video. It does exist. Furthermore, calling Resque.enqueue(AddVideo, 51061) a SECOND time, runs without any errors.

It is as if it takes more time to save the record in the database, than it takes to create the worker/job. But even this statement doesn't add up, since the object calls the Resque job only after the object is saved. In Rails, this is done via a callback method in the model (after_create).

Don't know if this plays a role in the issue. In an initializer file, I have:

Resque.before_fork do
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

Resque.after_fork do
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end
like image 905
Christian Fazzini Avatar asked Mar 12 '13 12:03

Christian Fazzini


1 Answers

This probably happens because the actual transaction in which the object is saved is not yet commited and the background job already started working on it.

You should switch the after_create to

after_commit :send_to_background_job, on: :create
like image 106
Milan Köpke Avatar answered Nov 17 '22 05:11

Milan Köpke