LoginSignup
1
0

More than 1 year has passed since last update.

Azure Logic Apps から起動した FastAPI の BackgroundTasks の完了をタイムアウト時間制約を超えて見守り続ける

Last updated at Posted at 2022-10-17

非同期なタスクが作成された場合の話です。
タスクを受け取った web server が 202 を返して、クライアントは 202 を以って処理を完了する(タスクの終了までを見守らない)パターンって結構あると思います。
今回は上記のパターンではなく、"クライアントからタスクが完了するまでを見守り続けること"を FastAPI の BackgroundTasks と Azure Logic Apps で検証して、Logic Apps のタイムアウト時間制約を超えて見守り続けることができたことに関して書きます。

前提: Azure Logic Apps の HTTP リクエストのタイムアウト時間に関して

マルチテナントだと 2 分でタイムアウトします。
https://learn.microsoft.com/ja-jp/azure/logic-apps/logic-apps-limits-and-config?tabs=azure-portal#timeout-duration

タイムアウト時間を超えて見守る"ポーリング アクション パターン"

詳しくは このlearn を見て欲しいのですが、要点は

  • クライアントからの HTTP リクエストの設定で非同期設定を ON にする
    • スクリーンショット 2022-10-17 14.05.51.png
  • タスクを受け取った際、web server から 202 のステータスコードと "タスクのステータスが分かるURL" を返させる
  • クライアント は "タスクのステータスが分かるURL" がステータスコードを200を返すまでポーリングし続ける
  • "タスクのステータスが分かるURL" が 200 を返すと、Azure Logic Apps の HTTP リクエストの結果も成功になる

です。

web server (FastAPI) 側の実装は以下のようにしました。
BackgroundTasks の実装は こちらの記事 を流用させて頂いております :bow_tone2:

# import は省略します

class Job(BaseModel):
    job_id: int
    def __call__(self):
        jobs[self.job_id] = self
        try:
            for _ in range(300):
                sleep(1)
            del jobs[self.job_id]
        finally:
            print("時間のかかる処理が終わりました")

jobs: dict[int, Job] = {}

@app.post("/api/{job_id}/", status_code=status.HTTP_202_ACCEPTED)
async def start(job_id: int, background_tasks: BackgroundTasks):
    t = Job(job_id=job_id)
    background_tasks.add_task(t)
    return JSONResponse(
        status_code=status.HTTP_202_ACCEPTED,
        content={},
        headers={"Location": f"https://example.com/api/{job_id}/"},
    )

@app.get("/api/{job_id}/")
async def get_status(job_id: int):
    if job_id in jobs:
        return JSONResponse(
            status_code=status.HTTP_202_ACCEPTED,
            content={},
            headers={"Location": f"https://example.com/api/{job_id}/"},
        )
    else:
        return JSONResponse(status_code=status.HTTP_200_OK, content={"message": f"{job_id}は実行していません"})

Azure Logic Apps から HTTP リクエストを送ってみた結果

Azure Logic Apps から HTTP リクエストを送ってみた結果、 5分後に成功となりました。

  • スクリーンショット 2022-10-17 14.05.06.png

余談

202 のステータスコードを受け取った場合、location ヘッダーのURLを見てポーリングを続ける のはRFCなどで決められた挙動なのかどうかが気になりました。調べてみると、RFCの202の仕様の解釈をめぐり、皆さん議論を重ねているみたいです:information_desk_person:

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0