假设我有以下基础Ruby类:
class BaseWorker
include Sidekiq::Worker
end
以及以下两个队列和一个助手类:
class Finder
class << self
def find(id)
AwesomeDBClass.find(id)
end
end
end
class Queue1 extend BaseWorker
def perform(variable)
if variable.some_attribute
...
end
end
end
class Queue2 extend BaseWorker
def perform id
local_variable = Finder.find(id)
Queue1.perform_async(local_variable)
end
end
以下测试工具:
let(:local_variable) do
double(:local_var, some_attribute: true)
end
let(:local_variable2) do
OpenStruct(some_attribute: true)
end
before do
allow(Finder).to_receive(:find).and_return(:local_variable)
... code that triggers queue2 ...
queue2.drain
queue1.drain
end
如果返回local_variable(double),则会失败:
undefined method `some_attribute' for {"__expired"=>false, "name"=>"local_variable"}:Hash
如果返回local_variable2(openstruct),则返回:
undefined method `some_attribute' for {"table"=>{"some_attribute"=>true}}:Hash
有趣的是,如果在queue2中检查(用puts
说),那么它们的值是正确的。
另外,在阅读两个库的代码时:
https://github.com/ruby/ruby/blob/trunk/lib/ostruct.rb#L93
似乎状态表明构造函数已经运行,但是其他一些东西(method_missing
绑定,例如类上的其他方法定义和/或assign_stubs
正在运行)没有发生。关于如何或为何如此发生的任何想法将不胜感激。
答案 0 :(得分:0)
TL; DR 使用简单哈希值代替OpenStruct
个实例作为perform
的参数。
Sidekiq
serializes Redis
的所有内容,请参阅Best Practices
。 OpenStruct
不适合作为传递给perform
的参数。
次要的旁注:自Sidekiq
overrides included
callback起,它将更加惯用于:
class BaseWorker
def self.extended base
base.send :include, Sidekiq::Worker
end
end