0
我发送用户更新到外部服务,定期,一个Sidekiq工人中运行的包装。每个用户都有自己的Sidekiq作业。 Sidekiq设置为使用20个线程。这是一个Rails 5.0.1应用程序,MRI Ruby 2.3.0。 Webserver是Passenger 5社区。Ruby对象突变
如果我在简化,代码如下所示:
class ProviderUserUpdateJob < ApplicationJob
queue_as :default
def perform(user_id)
user = User.find(user_id)
Provider::User.new(user).push_update
end
end
class Provider::User
def initialize(user)
@user = user
end
def push_update
SomeApiWrapper.call(
user_id: @user.id,
status: @user.status
)
end
....
end
现在,最大的问题,我只对生产,我终于逮住了通过查看日志可以这样概括:
class Provider::User
def initialize(user)
@user = user
end
def push_update
SomeApiWrapper.call(
user_id: @user.id, # Some user
status: @user.status # NOT THE SAME USER !!! (and I have no idea where he is coming from)
)
end
....
end
2个问题:
它是如何这甚至可能吗?它是否来自Provider :: User本质上是一个全局可访问的对象,因此,从线程到线程,所有东西都会混杂在一个变异的汤中?
如果我只用“功能性”的风格,没有任何实例,传递参数和输出从静态方法静态方法,它可以解决我的问题,还是我完全错了吗?我怎样才能解决这个问题?
最终,有没有什么办法可以真正对战测试这种代码,所以我可以肯定不会混合用户数据?
_“如果我在简化,代码看起来像这样” _ - 和它的bug仍然与简化的代码发生的呢? – Stefan
哈哈,好的。我的错。但尽管它被简化了,但问题的确切位置和行为仍与原始代码保持一致:“@user”在生产中随机地指向其他内容,从一行到另一行。连续两次调用“@user”变量之间绝对没有任何区别,这一点在这里并没有简化。 – gbarillot
对'id'或'status'的调用是否会产生副作用,使接收方发生变异?如果不是,那么'SomeApiWrapper.call'线程安全吗? – Stefan