FastAPI background task – nie przeciągaj czasu odpowiedzi

Jeśli chcesz wykonać operacje które nie muszą zostać wykonane przed zwróceniem odpowiedzi HTTP (wysłać email, zapisać bitmapę na blob storage), z rozwiązaniem przychodzi BackgroundTask. Jeśli proces biznesowy tego nie wymaga, to dlaczego klient serwera ma czekać kilka sekund na odpowiedź? Wystarczy że zwrócisz status HTTP 202 (zaakceptowane) i wykonasz zadanie w tle.

Dodanie i wykonanie BackgroundTask

FastAPI wspiera wstrzykiwanie zależności – instancję BackgroundTasks do której dodamy nasze zadania definiujemy jako parametr funkcji która jest dekorowana przez endpoint .

O to właśnie nam chodzi – FastAPI zajmie się orkiestracją (wykonaniem funkcji którą rejestrujemy) po obsłużeniu żadania HTTP.

Rejestrujemy zadania poprzez metodę .add_task która przyjmuje callable i opcjonalne argumenty które mają być przekazane podczas wykonania przekazanego callable. Innymi słowy sygnaturę którą można wywołać: czyli referencję do funkcji lub obiektu który implementuje __call__.

Dostajemy instancję BackgroundTasks która wykona zarejestrowane zadanie po zwróceniu odpowiedzi – oto właśnie nam chodzi – FastAPI zajmie się orkiestracją (wykonaniem funkcji którą rejestrujemy) po obsłużeniu żądania HTTP.

import asyncio

import uvicorn
from fastapi import FastAPI, BackgroundTasks

app = FastAPI()


async def task(request_id: int):
    # Ta funkcja uruchomi się po zwróceniu odpowiedzi, kiedy zarejestrujemy ją jako background task
    await asyncio.sleep(2)
    print(f'Handling background task for request id:{request_id}')


counter = 0



@app.get("/")
async def root(background_task: BackgroundTasks):
    global counter
    counter += 1
    background_task.add_task(task, data=counter)
    if counter % 2:
        raise Exception()
    print(f'Request id:{counter}')
    return counter


if __name__ == '__main__':
    uvicorn.run("main:app", reload=True)

Logi z konsoli dla 4 żądań bez odstępów w czasie.

Jak widzisz, w związku z naturą async, pierwszy background task wykonał się dopiero po zwróceniu odpowiedzi z czwartego żądania HTTP.

Przykład z nieobsłużonym wyjątkiem

Nawet jeśli nieobsłużony wyjątek nastąpi po zarejestrowaniu zadania, zarejestrowane zadanie nie zostanie wykonane

async def task(request_id: int):
    await asyncio.sleep(2)
    print(f'Handling background task for request id:{request_id}')


counter = 0

@app.get("/")
async def root(background_task: BackgroundTasks):
    global counter
    counter += 1
    background_task.add_task(task, request_id=counter)
    if counter % 2:
        raise Exception()
    print(f'Request id:{counter}')
    return counter

Wykonanie background task tylko dla żądań które zwróciły poprawną odpowiedź.

Szczegóły techniczne

  • Klasa BackgroundTasks pochodzi bezpośrednio z starlette.background, ale nie importuj jej stamtąd. Została zaimportowana/włączona bezpośrednio do FastAPI.
  • BackgroundTask jest uruchamiane po wysłaniu odpowiedzi. Nie ma więc możliwości zgłoszenia wyjątku dla klienta żądania kiedy coś pójdzie nie tak.

Źródła 

  1. https://fastapi.tiangolo.com/tutorial/background-tasks/

Udostępnij ten wpis


Dobrnąłeś do końca. Jeśli ten artykuł był dla Ciebie wartościowy i chcesz otrzymywać informacje o kolejnych, to zapraszam Cię do zapisania się do listy mailingowej. Gwarantuję zero spamu.

Radek.

Inne artykuły

ML w AWS – Sagemaker Autopilot

Automatyczne tworzenie modeli uczenia maszynowego z pełną widocznością w usłudze AWS Sagemaker – korzyści z wygenerowanego Jupyter Notebooka.

ML w AWS – Sagemaker Studio – IDE w przeglądarce

Sagemaker Studio – interaktywne środowisko dla Data Scientist. Z Jupyter Notebooks na pokładzie, oferuje współpracę, śledzenie eksperymentów i integrację z systemem kontroli wersji. Przegląd quasi …

ML w AWS – wstęp do usługi Sagemaker

Sagemaker: Wytwarzanie usług ML w chmurze AWS na nowym poziomie Odkryj potężną usługę Sagemaker, która gromadzi wszystkie niezbędne funkcjonalności związane z wytwarzaniem usług uczenia maszynowego w …

Rozwijasz czy produkujesz oprogramowanie?

Opracowywanie przepisów to proces uczenia się metodą prób i błędów. Nie oczekujesz, że pierwsza próba nowego dania wykonana przez szefa kuchni będzie ostatnią. W rzeczywistości …

Lean software development – eliminacja strat

Dowiedz się, jak wyeliminować marnotrawstwo i przyjąć zasady szczupłego rozwoju oprogramowania, aby dostarczyć więcej wartości swoim klientom przy mniejszym nakładzie pracy.

CD4ML: Continuous delivery for machine learning

Zacznijmy od początku: czym jest ciągłe dostarczanie (continuous delivery)? To podejście w wytwarzaniu oprogramowania, w którym wdrożenie nowej wersji jest decyzją biznesową. Ale jak to …