6

I'm working on a product that calls of perform_later jobs. This works for our product in production because we have a series of workers who will run all the jobs.

But, when I'm using the app locally, I don't have access to these workers, and I'd like to change all the perform_laters into perform_nows only when I use the app locally.

What's the best way to do this? One idea I had was to add something in my env file that would add a variable to make all perform_laters into perform_nows -- but I'm not sure what a flag or variable like that would look like.

Ideas?

acoravos
  • 63
  • 5

3 Answers3

15

The clean solution is to change the adapter in development environment.

In your /config/environments/development.rb you need to add:

Rails.application.configure do
  config.active_job.queue_adapter = :inline
end

"When enqueueing jobs with the Inline adapter the job will be executed immediately."

Leantraxxx
  • 4,506
  • 3
  • 38
  • 56
9

In your app you can have:

/my_app/config/initializers/jobs_initializer.rb

module JobsExt
  extend ActiveSupport::Concern

  class_methods do
    def perform_later(*args)
      puts "I'm on #{Rails.env} envirnoment. So, I'll run right now"
      perform_now(*args)
    end
  end
end

if Rails.env != "production"
  puts "including mixin"
  ActiveJob::Base.send(:include, JobsExt)
end

This mixin will be included on test and development environments only.

Then, if you have the job in:

/my_app/app/jobs/my_job.rb

class MyJob < ActiveJob::Base
  def perform(param)
    "I'm a #{param}!"
  end
end

You can execute:

MyJob.perform_later("job")

And get:

#=> "I'm a job!"

Instead of the job instance:

#<MyJob:0x007ff197cd1938 @arguments=["job"], @job_id="aab4dbfb-3d57-4f6d-8994-065a178dc09a", @queue_name="default">

Remember: Doing this, ALL your Jobs will be executed right now on test and dev environments. If you want to enable this functionality for a single job, you will need to include the JobsExt mixin in that job only.

Leantraxxx
  • 4,506
  • 3
  • 38
  • 56
2

We solved this by calling an intermediate method which then called perform_later or perform_now depending on Rails config:

def self.perform(*args)
  if Rails.application.config.perform_later
    perform_later(*args)
  else
    perform_now(*args)
  end
end

And simply updated environments configs accordingly

user3033467
  • 1,078
  • 15
  • 24