-1

Do anyone had problem recently with Fast API BackgroundTask?

Name: fastapi Version: 0.99.1

In the begin of the year I used and it was very fast to implement it. But now I tried everything and it runs like a normal function.

My code it was very long that cause I was reading multiple pdfs and doing the parser. So I tried with some basic example to test the core functionality but it didn't work still.

Examples that I tried:

--> First attempt (test)

--> Second attempt (test_asyncio) - I found someone talking about using asyncio

-router file

from fastapi import APIRouter, BackgroundTasks, Depends, status

from app.config.dbconfig import get_db
from app.services.pdf import ServicePdf
from app.utils.service_result import ServiceResult, handle_result

router = APIRouter(
    prefix="/pdf",
    tags=["pdf"],
    responses={404: {"description": "Not found"}},
)


@router.post("/test", status_code=status.HTTP_201_CREATED)
async def parse_candidate_pdf(
    background_tasks: BackgroundTasks,
    db: get_db = Depends(),
):
    background_tasks.add_task(ServicePdf(db).test, "name")
    return handle_result(ServiceResult(None), status.HTTP_201_CREATED)


@router.post("/test-asyncio", status_code=status.HTTP_201_CREATED)
async def parse_candidate_pdf_asyncio(
    background_tasks: BackgroundTasks,
    db: get_db = Depends(),
):
    background_tasks.add_task(ServicePdf(db).test_asyncio, "name")
    return handle_result(ServiceResult(None), status.HTTP_201_CREATED)

-service file

import asyncio
import time

from app.services.main import AppService

class ServicePdf(AppService):
    def test(self, name):
        time.sleep(5)
        print("Awake now!", name)

    async def test_asyncio(self, name):
        await asyncio.sleep(5)
        print("Awake now!", name)

What is happening:

  1. Enter on the route
  2. Just return the response after run all that have inside of the task that was suppose to be in background.

What I expected:

  1. Enter on the route
  2. Return the response
  3. Continue running the background task function on the background

Edit1: I created a new project, very basic only with the base logic and both functions worked! so it's not about the version

main.py

import time
import asyncio
from fastapi import FastAPI, BackgroundTasks

app = FastAPI()


async def process_data_asyncio(data: str):
    await asyncio.sleep(5)
    print(f"Processed data: {data}")


def process_data(data: str):
    time.sleep(5)
    print(f"Processed data: {data}")


@app.post("/process-data-asyncio/")
async def parse_asyncio(data: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(process_data_asyncio, data)
    return {"message": "Data processing started in the background."}


@app.post("/process-data/")
async def parse(data: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(process_data, data)
    return {"message": "Data processing started in the background."}


@app.get("/")
def home():
    return "api"

command to run:

uvicorn main:app --reload
4
  • 1
    Noone will be able to help you without enough code and version information to reproduce the behaviour. Commented Oct 11, 2023 at 14:56
  • Ohh Soryy, is the first time that I created a question, thank you for the clarification! Commented Oct 11, 2023 at 18:36
  • You might find this answer, as well as this answer and this answer helpful Commented Oct 12, 2023 at 6:40
  • Thank you Chris! 2nd answer is very aligned with what I'm trying to do. Gave me new insights, unfortunately It is still not working Commented Oct 13, 2023 at 19:19

1 Answer 1

1

After trying the edit1 code, I saw that the problem was not about the backgroundTask, it was about something else on my project, after so many tries I found the issue!

It had one custom middleware on main.py that is used to create logs, and this was making my backgroundTask work like a normal function:

@app.middleware("http")
async def custom_middleware_logging(request: Request, call_next):
    response = await call_next(request)
response_body = [chunk async for chunk in response.body_iterator]
response.body_iterator = iterate_in_threadpool(iter(response_body))
    # logging logic...
return response

Changing to a BackgroundTask for running the logs made it work!

Solution:

    @app.middleware("http")
    async def custom_middleware_logging(request: Request, call_next):
        response = await call_next(request)
        response.background = BackgroundTask(write_log_data, request, response)
    return response
Sign up to request clarification or add additional context in comments.

1 Comment

You might find this answer helpful as well.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.