【问题标题】:WARN: ArgumentError: missing keyword: user_id in job perform method警告:ArgumentError:缺少关键字:作业执行方法中的 user_id
【发布时间】:2026-01-22 02:00:01
【问题描述】:

我正在尝试使用 Sidekiq Shopify 工作人员将设计 current_user 传递给 rails 工作,但工作启动时,我收到了 WARN: ArgumentError: missing keyword: user_id。这是我在下面所做的,可能是我做错了。

OrderWebhookController

# frozen_string_literal: true

class OrderWebhooksController < ApplicationController
  include ShopifyApp::WebhookVerification

  def orders_paid
    params.permit!
    OrdersPaidJob.perform(shop_domain: shop_domain, webhook: webhook_params.to_h, user_id: current_user.id)
    head :no_content
  end

  private

  def webhook_params
    params.except(:controller, :action, :type)
  end
end

OrdersPaidJob

# frozen_string_literal: true

class OrdersPaidJob < ApplicationJob

  def perform(shop_domain:, webhook:, user_id:)
    shop = Shop.find_by(shopify_domain: shop_domain)

    webhook.to_json

    shop.with_shopify_session do
      customer = webhook['customer']

      payload = {
        user_id: user_id,
        email: customer['email'],
        amount_spent: customer['total_spent'],
        first_name: customer['first_name'],
        last_name: customer['last_name'],
        point_balance: (customer['total_spent']),
        recorded_on: Time.now
      }

      customer_records = [].tap do |array|
        array << payload
      end

      customer_exists(customer) ? CustomerDetail.upsert(customer_records) : CustomerDetail.insert_all(customer_records)
    end
  end

  private

  def earning_rules
    EarningRule.order_rule || 0
  end

  def customer_exists(customer)
    CustomerDetail.find_by_email(customer['email'])
  end
end

日志错误

error_message\":\"missing keyword: user_id\",\"error_class\":\"ArgumentError\",\"failed_at\":1574158701.8283021,\"retry_count\":4,\"retried_at\":1574159903.266159}"}
2019-11-19T10:39:09.892Z pid=6341 tid=oxrqw3mjx WARN: ArgumentError: missing keyword: user_id
2019-11-19T10:39:09.893Z pid=6341 tid=oxrqw3mjx WARN: /Users/tiwa/RubymineProjects/ShopifyLoyaltyApp/app/jobs/orders_paid_job.rb:5:in `perform'
/Users/tiwa/.gem/ruby/2.6.2/gems/activejob-6.0.1/lib/active_job/execution.rb:39:in `block in perform_now'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:112:in `block in run_callbacks'
/Users/tiwa/.gem/ruby/2.6.2/gems/i18n-1.7.0/lib/i18n.rb:297:in `with_locale'
/Users/tiwa/.gem/ruby/2.6.2/gems/activejob-6.0.1/lib/active_job/translation.rb:9:in `block (2 levels) in <module:Translation>'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `instance_exec'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/core_ext/time/zones.rb:66:in `use_zone'
/Users/tiwa/.gem/ruby/2.6.2/gems/activejob-6.0.1/lib/active_job/timezones.rb:9:in `block (2 levels) in <module:Timezones>'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `instance_exec'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks'

任何帮助将不胜感激。

【问题讨论】:

    标签: ruby-on-rails shopify sidekiq shopify-app rails-activejob


    【解决方案1】:

    在您的情况下,您可以按如下方式访问此传递的参数:

      def perform(shop_domain:, webhook:, user_id:)
    

    改为:

      def perform(params)
    

    然后是params["user_id"] 等等。

    Sidekiq 不支持命名参数https://github.com/mperham/sidekiq/wiki/Best-Practices#1-make-your-job-parameters-small-and-simple

    但是,有一些很好的解决方法,例如:https://github.com/mperham/sidekiq/issues/2372#issuecomment-469660538

    这是上面来源的copypasta:

    # jobs/job.rb
    class Job
      include Sidekiq::Worker
    
      # ... more default options here
    
      def perform(params={})
        params = params.to_h.transform_keys(&:to_sym)
        execute params
      end
    end
    
    # jobs/greet_job.rb
    class Greet < Job
      def execute(name: "there")
        puts "Hi #{name}!"
      end
    end
    So now all jobs simply define execute instead of defining perform.
    
    And it even works nicely in specs:
    
    # spec/greet_job_spec.rb
    expect(Greet).to have_enqueued_sidekiq_job(name: "Lloyd Christmas")
    

    【讨论】:

    • 但如果我删除user_id:,这些论点就会起作用。问题只是我在保存到数据库的哈希中需要current_user,这就是我添加user_id: 作为参数的原因。