kenju's blog

About Programming and Mathematics

Sidekiq Best Practices: パラメーターにModelを渡す時はObject InstancesではなくIDsを渡す

github.com

tl;dr

  • Sidekiqで非同期ジョブを実行する時、IDsを渡し、ジョブ内で再度モデルをfind()して使う
  • オブジェクトのインスタンスを渡すと、ジョブがキューに存在する間にインスタンスの値が変更されうる
    • 例:Userモデルのname値がenqueしたタイミングと、非同期ジョブ内で実際にその値を使うタイミングとの間に変更されていて、データ不整合が発生する

理由

Queueにenqueueされている間にインスタンスの値が変更される可能性は多いにあるのだから、仕組みを考えたら当たり前ではある。

追記:この理由がおそらく違う、と教えてもらった。が、いまいちまだ理解できていないのでTODO

Don’t save state to Sidekiq, save simple identifiers. Look up the objects once you actually need them in your perform method.

具体例

NG Pattern

class AwesomeController
  def create
    user_id = ***
    user = User.find(user_id)
    AwesomeJob.perform_later(user: user)
  end
end

class AwesomeJob
  # @param [User] user
  def perform(user:)
    # handle user instance
  end
end

OK Pattern

class AwesomeController
  def create
    user_id = ***
    AwesomeJob.perform_later(user_id: user_id)
  end
end

class AwesomeJob
  # @param [Integer] user_id
  def perform(user_id:)
    user = User.find(user_id)
    # handle user instance
  end
end