sidekiq工作者中的Ruby Object变异

时间:2017-01-24 13:36:22

标签: ruby-on-rails ruby thread-safety sidekiq

我有一个包装器,定期将用户更新发送到外部服务,在Sidekiq worker中运行。每个用户都有自己的Sidekiq工作。 Sidekiq设置为使用20个线程。它是Rails 5.0.1应用程序,MRI Ruby 2.3.0。 Webserver是Passenger 5社区。

如果我过度简化,代码如下:

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个问题:

  1. 这怎么可能呢?它是来自Provider :: User本质上是一个全局可访问的对象,因此,从线程到线程,一切都变成了变异汤?!

  2. 如果我只使用&#34; functional&#34;样式,没有任何实例,从静态方法传递参数和输出到静态方法,它能解决我的问题还是我完全错了?我怎样才能解决这个问题?

  3. 最终,有没有办法真正对这种代码进行测试,以便我可以确保不混合用户数据?

1 个答案:

答案 0 :(得分:0)

好的......结果发现它是一个虚拟数据问题。我只是花了2个小时试图通过复杂的解释弄明白,但答案只是在我的数据库中。干得好: - /