diff --git a/Docs/Tasks.md b/Docs/Tasks.md index a71b401..6d21909 100644 --- a/Docs/Tasks.md +++ b/Docs/Tasks.md @@ -609,6 +609,8 @@ Synchronous I/O in the async startup path violates the "Async Everything" design ### Task 21 — Consolidate start_daemon / wait_for_fail2ban duplicates +**Status:** Completed + **Severity:** Low **Where:** @@ -633,6 +635,8 @@ Any change to the daemon-start retry logic (timeouts, exception handling) must c ### Task 22 — Remove DEFAULT_BLOCKING_EXECUTOR dead code +**Status:** Completed + **Severity:** Low **Where:** diff --git a/backend/app/utils/async_utils.py b/backend/app/utils/async_utils.py index 6ff902b..11c1c83 100644 --- a/backend/app/utils/async_utils.py +++ b/backend/app/utils/async_utils.py @@ -7,6 +7,7 @@ running blocking callables without stalling the FastAPI event loop. from __future__ import annotations import asyncio +import functools from concurrent.futures import ThreadPoolExecutor from typing import Callable, ParamSpec, TypeVar @@ -37,6 +38,8 @@ async def run_blocking( The callable return value. """ loop = asyncio.get_running_loop() - if executor is None: - return await asyncio.to_thread(func, *args, **kwargs) - return await loop.run_in_executor(executor, func, *args, **kwargs) + executor = DEFAULT_BLOCKING_EXECUTOR if executor is None else executor + if kwargs: + func = functools.partial(func, *args, **kwargs) + return await loop.run_in_executor(executor, func) + return await loop.run_in_executor(executor, func, *args)