ActiveJob - what's the difference between MyJob.new.perform and MyJob.perform_now?

Viewed 2487

I've found that ActiveJob could triggered by MyJob.new.perform and MyJob.perform_now.

My question is: what's the difference between these two calls?

1 Answers

The perform_now method is a wrapper around the perform method of the ActiveJob::Execution class. The source code(shortened for answer) for both these methods can be found here on GitHub. The source code is as follows:

module ActiveJob
  module Execution
    extend ActiveSupport::Concern
    include ActiveSupport::Rescuable

    # Includes methods for executing and performing jobs instantly.
    module ClassMethods
      # Method 1
      def perform_now(*args)
        job_or_instantiate(*args).perform_now
      end
    end

    # Instance method. Method 2
    def perform_now
      self.executions = (executions || 0) + 1

      deserialize_arguments_if_needed
      run_callbacks :perform do
        perform(*arguments)
      end
    rescue => exception
      rescue_with_handler(exception) || raise
    end

    # Method 3
    def perform(*)
      fail NotImplementedError
    end

MyJob.perform_now This call, invokes the class method, perform_now (Method 1 in the snippet), which internally instantiates an object of MyJob and calls the instance method perform_now (Method 2 in the snippet). This method deserializes arguments if required, and then runs callbacks that we may have defined in our job file for MyJob. After this, it calls the perform method(Method 3 in our snippet), which is an instance method of the ActiveJob::Execution class.

MyJob.new.perform If we use this notation, we basically instantiate an instance of the job by ourselves, and then call the perform method (Method 3 of our snippet) on the job. By doing so, we skip the deserialization provided by perform_now and also skip running any callbacks written on our job, MyJob.

Illustrated with an example:

# app/jobs/my_job.rb

class UpdatePrStatusJob < ApplicationJob
  before_perform do |job|
    p "I'm in the before perform callback"
  end

  def perform(*args)
    p "I'm performing the job"
  end
end

MyJob.perform_now gives the output:

"I'm in the before perform callback"
"I'm performing the job"

whereas MyJob.new.perform gives the output:

"I'm performing the job"

This article by Karol Galanciak explains jobs in detail and should be an interesting read if you're looking for more information on how jobs work.

Related