Фоновые синхронные задачи
Почему фоновые таски не асинхронные? Пример
from fastapi import BackgroundTasks, FastAPI
app = FastAPI()
def write_notification(email: str, message=""):
with open("log.txt", mode="w") as email_file:
content = f"notification for {email}: {message}"
email_file.write(content)
@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
background_tasks.add_task(write_notification, email, message="some notification")
return {"message": "Notification sent in the background"}
В примере выше есть задача, которая является синхронной функцией. Как фоновая задача может быть синхронной?
Ответы (1 шт):
Автор решения: hedgehogues
→ Ссылка
В исходниках видно, что fastapi, в зависимости от того: синхронная функция или нет, -- решает делать над ней декоратор или не делать его.
import asyncio
import typing
from starlette.concurrency import run_in_threadpool
class BackgroundTask:
def __init__(
self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any
) -> None:
self.func = func
self.args = args
self.kwargs = kwargs
self.is_async = asyncio.iscoroutinefunction(func)
async def __call__(self) -> None:
if self.is_async:
await self.func(*self.args, **self.kwargs)
else:
await run_in_threadpool(self.func, *self.args, **self.kwargs)
class BackgroundTasks(BackgroundTask):
def __init__(self, tasks: typing.Sequence[BackgroundTask] = []):
self.tasks = list(tasks)
def add_task(
self, func: typing.Callable, *args: typing.Any, **kwargs: typing.Any
) -> None:
task = BackgroundTask(func, *args, **kwargs)
self.tasks.append(task)
async def __call__(self) -> None:
for task in self.tasks:
await task()