我的生产中只有一个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
。我不明白为什么初始化类会返回此错误。
有什么想法吗? 感谢
答案 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'
# ...
}