@dectarin が述べたように、複数のワーカーが複数のジョブ キューをリッスンすると、ユーザーごとに 1 つのジョブのみが実行されるようにすることが難しくなります。
ジョブがいくつかのステップを経ると、よりうまくいくと思います。
- ユーザーがジョブを送信
- 他のジョブが実行されなくなるまで、ジョブはユーザーごとにキューに入れられます
- コーディネーターは、ワーカーによって消費されるアクティブなジョブ キューにジョブを配置します
- ワーカーがジョブを取得して実行する
- ワーカーは結果キューに結果をポストします
- 結果はユーザーに送信されます
ジョブがシステムに送信される方法がわからないため、実際のユーザーごとの MessageQueue が待機中のキューに入れるのに最適な方法であるかどうかを判断するのは困難です。たとえば、ジョブが既にメールボックスにある場合、それも同様に機能する可能性があります。または、キューに入れられたジョブをデータベースに保存します。ボーナスとして、ユーザーがキューに入れられたジョブを検査および管理するための小さなフロントエンドを作成できるようになります。
選択内容に応じて、ユーザー制約ごとに 1 つのジョブを調整する洗練された方法を見つけることができます。
たとえば、ジョブがデータベースにある場合、データベースは物事の同期を維持し、複数のコーディネーター ワーカーが次のループを通過する可能性があります。
while( true ) {
if incoming job present for any user {
pick up first job from queue
put job in database, marking it active if no other active job is present
if job was marked active {
put job on active job queue
}
}
if result is present for any user {
pick up first result from result queue
send results to user
mark job as done in database
if this user has job waiting in database, mark it as active
if job was marked active {
put job on active job queue
}
}
}
または、待機中のジョブがユーザーごとのメッセージ キューにある場合、トランザクションはより簡単になり、ループを通過する単一のコーディネーターはマルチスレッドについて心配する必要がなくなります。
データベースとキュー全体で物事を完全にトランザクション化するのは難しいかもしれませんが、必ずしも必要ではありません。保留状態を導入することで、ステップが失敗した場合にジョブが失われないように注意を怠ることができます。