Search code examples
ruby-on-railssidekiqpuma

Creating a background job from a thread


I have an application that uses a third party service. My application can create authentication for that service which it stores in the DB. That authentication can't be committed in the same transaction because it needs to be in the DB to be used. To make this work, I open a thread to create a new DB connection and commit the authentication record immediately

I seem to be running into a problem by using this thread. Without the thread, all the code runs smoothly, everything works up until I have to use the auth, and then I get a 401 because it isn't in the DB yet

Below you can follow what is happening. When I create a user, it triggers different callbacks until you get to run_backround_job. It seems to hang on perform_later. When I remove the thread code and have it execute immediately, everything works. But for some reason it get's stuck on queueing a job if it is in a separate thread.

Here's code that represents what is happening:

class User < ApplicationRecord
  belongs_to :organization

  after_create :use_auth

  def use_auth
    organization.find_or_create_auth
  end
end

class Organization < ApplicationRecord
  has_many :authentications
  has_many :users

  def find_or_create_auth
    Thread.new do
      ApplicationRecord.connection_pool.with_connection do
        authentications.find_or_create_by(name: name)
      end
    end.join.value
  end
end

class Authentication < ApplicationRecord
  belongs_to :organization

  after_create :run_background_job

  def run_background_job
    AuthBackgroundJob.perform_later(id)
  end
end

rails (5.0.0) puma (3.6.0) sidekiq (4.1.4)


Solution

  • Use after_commit :run_background_job.