Rails 生产服务器 config.cache_classes = true 不会为活动作业正确重新加载自定义服务 类

Rails production server config.cache_classes = true does not reload custom service classes correctly for active job

我在 Rails 6.1.3.2

中使用 Active Job 和 sidekiq 适配器

奇怪的是,自定义服务单例方法在 Active Job 中调用时会丢失。

notify_message_event_job.rb

module Chats
  class NotifyMessageEventJob < ApplicationJob
    queue_as: default

    def perform(message:, event:)
      Rails.logger.info(PushNotification::Service.name)
      Rails.logger.info(PushNotification::Service.singleton_methods.inspect)
      PushNotification::Service.create(
        user: message.user,
        notification: message.content
      )
    end
  end
end

lib/push_notification/service.rb

module PushNotification
  class Service
    class << self
      def create(user:, notification:)
        // 
      end
    end
  end
end

下面一行:

NotifyMessageEventJob.perform_now(message: message, event: event)

产生以下错误:

[ActiveJob] [Chats::NotifyMessageEventJob] [b1d934c8-afe0-44a0-bc22-44d40eea7d3d] Performing Chats::NotifyMessageEventJob (Job ID: b1d934c8-afe0-44a0-bc22-44d40eea7d3d) from Sidekiq(default) enqueued at with arguments: {:message=>#<GlobalID:0x00007fe5bc4f6b00 @uri=#<URI::GID gid://interview-server/ChatMessage/156>>, :event=>"NEW_MESSAGE"}

[ActiveJob] [Chats::NotifyMessageEventJob] [b1d934c8-afe0-44a0-bc22-44d40eea7d3d] PushNotification::Service

[ActiveJob] [Chats::NotifyMessageEventJob] [b1d934c8-afe0-44a0-bc22-44d40eea7d3d] [:yaml_tag]

[ActiveJob] [Chats::NotifyMessageEventJob] [b1d934c8-afe0-44a0-bc22-44d40eea7d3d] Error performing Chats::NotifyMessageEventJob (Job ID: b1d934c8-afe0-44a0-bc22-44d40eea7d3d) from Sidekiq(default) in 40.9ms: NoMethodError (undefined method `create' for PushNotification::Service:Class):

正如你在日志中看到的,class PushNotification::Service 被正确加载,但是只有 yaml_tag 方法。

当我 运行 在 rails 控制台中使用以下方法时:

2.7.3 :001 > PushNotification::Service.singleton_methods

我得到:

=> [:create, :ios_app_name, :config, :create_apnsp8_app, :create_apns2_app, :create_android_app, :create_ios_apps, :flush, :notification_enabled?, :create_gcm_notification, :create_apn_notification, :android_app_name, :yaml_tag]

RSpec 测试也通过了。我在生产服务器中收到此错误。什么原因?我正在拔头发。

更新

我发现如果我设置 config.cache_classes = false,代码将毫无问题地继续。

但是,我一重新设置config.cache_classes = true,同样的错误又会发生。当然,每次更改代码时,我都会重新启动生产 rails 服务器。

我删除了整个源代码,重新启动了服务器。再次拉取代码,重启rails,问题并没有消失

如有任何建议,我们将不胜感激。

似乎是 zeitwerk autoloading mode 的问题,它在 Rails 6

中作为默认值引入

我暂时选择退出 config/environments/production.rb:

config.load_defaults 6.1
config.autoloader = :classic