Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FastAPI Background task in middleware

I'm trying to add background tasks to my middleware, but haven't found any official way to do it in their docs, this is what I have tried so far:

async def task1():
    logging.info("Waiting ...")
    time.sleep(5)
    logging.info("Waited.")

@app.middleware("http")
async def add_process_time_header(request, call_next, bt=Depends(BackgroundTasks)):
    a = bt.dependency()
    a.add_task(task1)
    a()

    return await call_next(request)

This is blocking my requests, also shouldn't I be able to call async functions without await? I want to completely ignore the results of the background tasks, I dont need results from bg tasks

like image 257
redigaffi Avatar asked Sep 03 '25 03:09

redigaffi


2 Answers

You can attach a BackgroundTask instance to a response to instruct Starlette to perform a background task after the response is returned.

Code taken directly from this github issue thread and worked for me perfectly:

from starlette.background import BackgroundTask
from somewhere import your_background_task

@app.middleware("http")
async def middleware(request: Request, call_next):

    # middleware code

    response.background = BackgroundTask(your_background_task, arg)
    return response
like image 161
alecxe Avatar answered Sep 05 '25 00:09

alecxe


I found some way to solve your problem, i think you can find better way,but for now you can use like this:

import logging
import time
import asyncio
from fastapi import FastAPI, Request

app = FastAPI()
@app.get("/")
async def call_api():
    await asyncio.sleep(5)
    return True

async def task1():
    logging.info("Waiting ...")
    await asyncio.sleep(5)
    logging.info("Waited.")

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()

    response , res__task1 = await asyncio.gather(*[call_next(request),task1()])
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    print(process_time)

    return response

A total of 5 seconds are spent on all tasks

like image 31
milad_vayani Avatar answered Sep 05 '25 00:09

milad_vayani