【问题标题】:Delayed::DeserializationError undefined method `has_key?'Delayed::DeserializationError 未定义方法“has_key?”
【发布时间】:2014-05-06 16:02:04
【问题描述】:

我只有在生产中有一个错误。我无法在开发环境中重现该问题。 我有一个主类,它在后台作业中为流程数据初始化多个类,但这在delayed_job 中并不顺利,这是我的两个类的简化。

处理类

 class Handler
   def initialize(setting)
      @setting = setting
   end

   def process
     0.upto(11) do |index|
       # data = some code in local method...
       launch_process(data)
     end
   end 

   protected

   def launch_process(data)
    Process.new(
      @setting,
      data: data
    ).boot
   end
 end

由 Handler 类调用的进程类

class Process
  def initialize(setting, options = {})
    @setting = setting
    options.each { |k,v| instance_variable_set("@#{k}", v) }
  end

  def boot
    self.delay.launch_retrieve
  end
end

但是当进程类被执行时,delayed_job 报错:Delayed::DeserializationError: Job failed to load: undefined method has_key? for nil:NilClass。我不明白为什么类的初始化会返回这个错误。

有什么想法吗? 谢谢

【问题讨论】:

  • 您使用的是非 DB 访问器属性吗?如果是,DJ 会报错。
  • 我有一个用于设置和选项的 attr_accessor,但对于动态 instance_variable_set 没有。但是在开发环境中,我没有这个问题。
  • K,我遇到了 DJ 问题,我在后台作业中使用 attr_accessor,我在开发模式下运行 DJ 并查看了 DJ active_record 对象,我发现该属性不在属性 yml 键中。
  • 您是否在开发模式下运行延迟作业守护程序?
  • 是的,mongoid 可以正常工作。这个问题只在生产上,真的很奇怪。而且我没有调试的可见性,这很糟糕^^

标签: ruby mongoid delayed-job


【解决方案1】:

有时当我们升级库时,延迟的作业仍然保留旧的引用。

尝试在日志中找到delayed_job的id并播放解析其处理程序到ruby以找到错误的引用

j = DelayedJob.find(XXX)
data = YAML.load_dj(j.handler)
data.to_ruby

我发了pull request 来帮助解决这个问题。

同时你可以使用这条线

# config/initializers/delayed_job.rb

# Monkey patch to use old class references
module Psych

  class << self; attr_accessor :old_class_references end
  @old_class_references = {}

  class ClassLoader
    private

    def find klassname
      klassname = ::Psych.old_class_references[klassname] || klassname
      @cache[klassname] ||= resolve(klassname)
    end
  end

  module Visitors
    class ToRuby < Psych::Visitors::Visitor
      def revive klass, node
        if klass.is_a? String
          klassname = ::Psych.old_class_references[klass] || klass
          klass = Kernel.const_get(klassname) rescue klassname
        end
        s = register(node, klass.allocate)
        init_with(s, revive_hash({}, node), node)
      end
    end
  end
end

# Add all old dependencies (hash keys) pointing to new references (hash values)
Psych.old_class_references = {
  'ActiveRecord::AttributeSet' => 'ActiveModel::AttributeSet'
  # ...
}

【讨论】:

  • 感谢 Raúl,所有项目现已迁移到 Sidekiq ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
相关资源
最近更新 更多