Delayed :: DeserializationError undefined方法`has_key?'

时间:2014-03-27 15:09:18

标签: ruby mongoid delayed-job

我的生产中只有一个bug。我无法在开发环境中重现这个问题。 我有一个主类,它在后台作业中为进程数据初始化了几个类,但是在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。我不明白为什么初始化类会返回此错误。

有什么想法吗? 感谢

1 个答案:

答案 0 :(得分:1)

有时,当我们升级libs时,延迟的工作仍然保留着旧的参考。

尝试在日志中找到delay_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'
  # ...
}