私には、次のような仕事を行う約 10 人の労働者がいます。
user = User.find_or_initialize_by(email: 'some-email@address.com')
if user.new_record?
# ... some code here that does something taking around 5 seconds or so
elsif user.persisted?
# ... some code here that does something taking around 5 seconds or so
end
user.save
問題は、特定の時間に 2 人以上のワーカーがこのコードを正確な時間に実行することです。そのため、後で 2 人以上のユーザーが同じemail
.
一意の電子メールは条件付きであるため、私の状況では DB 一意のインデックスを作成することはできemail
ません。一意の電子メールを持つべきユーザーもいれば、持たないユーザーもいます。
User
私のモデルには一意性の検証があることに言及することは注目に値しますが、 と の間.find_or_initialize_by
に.save
、ユーザー オブジェクトが既に作成されているかどうかに依存するコードがあるため、それでも役に立ちません。
悲観的ロックと楽観的ロックを試しましたが、役に立たなかった、または適切に実装していなかっただけかもしれません...これに関する提案があれば.
私が考える唯一の解決策は、これらのコード行が実行されるたびに他のスレッド (Sidekiq ジョブ) をロックすることですが、これを実装する方法がよくわかりませんし、これが提案可能なアプローチであるかどうかもわかりません。
助けていただければ幸いです。
編集
私の特定のケースでは、このジョブは上で述べたものよりも少し複雑であるため、ジョブに電子メールパラメーターを配置するのは難しいでしょう。ジョブは実際には、ジョブのセクションが上記のコードであるエクスポート スクリプトです。上記の機能を別の別のワーカーに分離することも可能だとは思いません...ジョブフロー全体がシリアルである必要があり、どの部分も並列/非同期で処理されるべきではないためです。このジョブは、最終的にマスター ジョブによって管理される別のジョブによって管理されるジョブの 1 つにすぎません。