REST APIを実装しています。このAPIは、長時間実行される複数のバックエンドタスクを開始します。RESTfulWebサービスクックブックを読んでおり、推奨はHTTP 202/Accepted with a Content-Locationを返すことです処理中のタスクを指すヘッダー(例: http://www.example.org/orders/tasks/1234 )、クライアントにこのURIをポーリングして、長時間実行されるタスクの更新を求めます。
アイデアは、REST APIがメッセージをすぐにキューに投稿し、バックグラウンドワーカーの役割がキューからメッセージを取得し、キューを使用して複数のバックエンドタスクをスピンアップすることです。このアプローチでは、一意のIDをタスクに割り当て、続いてクライアントがContent-Location URIにGETを発行することでタスクのステータスを要求する方法がわかります。
REST APIがすぐにキューに投稿する場合は、GUIDを生成し、キューに追加されるメッセージの属性としてアタッチできますが、リクエストのステータスを取得するのは面倒です。
もう1つのオプションは、REST APIにデータベースにエントリを追加し(新しい注文IDで注文をしましょう)、初期ステータスを設定してから、メッセージをAPIは、クライアントがタスクのステータスを確認するときに使用するために、Content-LocationヘッダーのURIでこの新しい注文IDを返します。
どういうわけか、最初にデータベースエントリを追加してから、メッセージをキューに追加すると逆に見えますが、要求をキューに追加するだけでは進捗を追跡するのが難しくなります。
推奨されるアプローチは何ですか?
あなたの洞察に感謝します。
あなたのシステムは次のように見えると思います。クライアントからリクエストを受信するRESTサービスがあります。要求をビジネスロジックが理解できるコマンドに変換します。これらのコマンドをキューに入れます。これらのコマンドを処理してキューから削除し、結果をクライアントに応答できるRESTサービスに送信できる単一または複数のワーカーがあります。
長時間実行するタスクによってクライアント接続がタイムアウトするため、応答を送信できないという問題。したがって、できることは、コマンドをキューに入れてポーリングリンクを追加した後、承認された202を送信することです。これにより、クライアントは変更をポーリングできます。タスクには複数のサブタスクがあるため、ステータスの変更が保留中および完了しただけでなく、進行状況があります。
GET /tasks/23461/status
などのリクエストに応答できます。これは、サブタスクまたはタスク全体が完了すると、ワーカーがデータベースを更新する必要があることを意味します。GET /tasks/23461/status
などのリンクが作成され、通知サービスを介してそのリンクがクライアントに送信されます。その後、クライアントはリンクを使用してステータスを更新できます。RESTサービスがデーモンとして実行される場合、最後の方法が最善の解決策だと思います。これは、Websocket、ポーリング、SSEなど、必要なものを使用できる専用の通知サービスに通知責任を移動できるためです。 RESTサービスを強制終了せずに折りたたむことができるため、RESTサービスは安定した高速なままです。 202を使用して手動更新リンクも送り返す場合、クライアントは手動更新を実行できます(人間が制御するクライアントを想定しています)。そのため、通知サービスが利用できない場合、グレースフルデグラデーションなどが発生します。通知サービスはタスクについて何も知らず、クライアントにデータを送信するだけなので、通知サービスを維持する必要はありません。ワーカーは、通知の送信方法とハイパーリンクの作成方法について何も知る必要はありません。ほぼ純粋なRESTクライアントになるため、クライアントコードの保守も簡単になります。唯一の追加機能は、頻繁に変更されない通知リンクのサブスクリプションです。