You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让Rails控制器中add方法通过Delayed Job延迟执行?

Fixing Delayed Job Not Executing Your add Method in Rails Controller

Let's break down why your current setup isn't working and walk through the fixes step by step.

The Core Issue in Your Code

Your current line add(a, b).delay is doing the opposite of what you want: it immediately runs add(a, b), then tries to call delay on whatever that method returns (which is nil since your add method is empty). Delayed Job can't delay a nil value, so nothing gets queued up.

Step 1: Fix the Delay Syntax (Quick Fix, Not Ideal Long-Term)

To actually delay the execution of the add method itself, you need to call delay on the controller instance first, then invoke the method:

def create
  # This tells Delayed Job to queue the `add` method with arguments a and b
  delay.add(a, b)
end

But wait—controllers are not designed to be serialized for background jobs. Controllers hold references to request-specific objects (like params, session, or response) that can't be safely serialized and deserialized by Delayed Job. This might lead to errors or unexpected behavior down the line.

Step 2: Best Practice - Use a Dedicated Worker Class

The cleanest and most reliable way to handle background tasks in Rails (with Delayed Job) is to move your business logic into a separate worker class. Here's how:

  1. Create a new worker file in app/workers/:
# app/workers/referral_add_worker.rb
class ReferralAddWorker
  def perform(a, b)
    # Put your actual business logic from the `add` method here
    # Example:
    # result = a + b
    # ReferralRecord.create(result: result)
  end
end
  1. Update your controller to enqueue this worker:
class V1::LpDeveloperReferralsController < V1::BaseController
  def create
    # Grab your a and b values from params first (assuming they come from the request)
    a = params[:a].to_i # Adjust type as needed
    b = params[:b].to_i

    # Queue the worker with Delayed Job
    ReferralAddWorker.new.delay.perform(a, b)

    # Or use the explicit enqueue syntax if you prefer:
    # Delayed::Job.enqueue ReferralAddWorker.new, args: [a, b]
  end
end

Step 3: Verify Delayed Job Setup

Make sure your Delayed Job installation is complete and running:

  • Check that gem 'delayed_job_active_record' (or your chosen backend) is in your Gemfile, then run bundle install.
  • Run the migration to create the delayed_jobs table:
    rails generate delayed_job:active_record
    rails db:migrate
    
  • Start the Delayed Job worker process (this is critical—jobs won't run unless the worker is active):
    rails jobs:work
    
    For production, use a process manager like systemd or foreman to keep the worker running continuously.

Step 4: Ensure Your Arguments Are Serializable

Delayed Job needs to serialize the arguments you pass to the background task. Avoid passing complex objects (like unsaved ActiveRecord instances, request objects, or custom classes without serialization support). Instead:

  • Use simple types (strings, integers, floats).
  • If you need to pass an ActiveRecord object, pass its id and fetch it again in the worker:
    # Controller
    user_id = current_user.id
    ReferralAddWorker.new.delay.perform(user_id, a, b)
    
    # Worker
    def perform(user_id, a, b)
      user = User.find(user_id)
      # Do something with user, a, and b
    end
    

Testing It Out

After making these changes:

  1. Start your Rails server and send a request to the create endpoint.
  2. Check your delayed_jobs table (run rails c then Delayed::Job.all—you should see a new job entry).
  3. Make sure the worker is running, and verify that the perform method in your worker executes as expected.

内容的提问来源于stack exchange,提问作者Kingsley Simon

火山引擎 最新活动