1
votes

Earlier, I had posted this question – and thought it was resolved:

Rails background worker always fails first time, works second

However, after continuing with tests and development, the error is back again, but in a slightly different way.

I'm using Sidekiq (with Rails 3.2.8, Ruby 1.9.3) to run background processes, after_save. Below is the code for my model, worker, and controller.

Model:

class Post < ActiveRecord::Base

  attr_accessible :description, 
                  :name,
                  :key 

  after_save :process

  def process
    ProcessWorker.perform_async(id, key) if key.present?
    true
  end

  def secure_url
    key.match(/(.*\/)+(.*$)/)[1]
  end

  def nonsecure_url
    key.gsub('https', 'http')
  end

end

Worker:

class ProcessWorker
  include Sidekiq::Worker

  def perform(id, key)

    post = Post.find(id)
    puts post.nonsecure_url

  end
end     

(Updated) Controller:

def create
  @user = current_user
  @post = @user.posts.create(params[:post])
  render nothing: true
end

Whenever jobs are first dispatched, no matter the method, they fail initially:

undefined method `gsub' for nil:NilClass

Then, they always succeed on the first retry.

I've come across the following github issue, that appears to be resolved – relating to this same issue:

https://github.com/mperham/sidekiq/issues/331

Here, people are saying that if they create initializers to initialize the ActiveRecord methods on the model, that it resolves their issue.

To accomplish this, I've tried creating an initializer in lib/initializers called sidekiq.rb, with the following, simply to initialize the methods on the Post model:

Post.first

Now, the first job created completes successfully the first time. This is good. However, a second job created fails the first time – and completes upon retry... putting me right back to where I started.

This is really blowing my mind – has anyone had the same issue? Any help is appreciated.

1
It's telling you that key is a NilClass. Can you show us in the controller where you are attaching the key to Post? - rescuecreative
I've added my controller code to the original post - cmw
It looks like your worker is firing when the object is saved, but your key is being added after the object is saved. You'll need to call the :process method after the attribute is updated, so the key is present when the worker fires. - rescuecreative
Hmm, now I'm getting a different error – it's saying it can't find the ID of the object that was just saved Couldn't find Post with id=46 - cmw
Well, at this point it's kind of hard to tell... Sometimes, sidekiq can initialize your worker before the model actually finishes saving to the database. Try using an after_commit callback instead of after_save in your model like: after_commit :process, :on => :create. Check out this article. - rescuecreative

1 Answers

2
votes

Change your model callback from after_save to after_commit for the create action. Sometimes, sidekiq can initialize your worker before the model actually finishes saving to the database.

after_commit :process, :on => :create