From f91eae9e03b4458a124a69cce8f0f555ef61c3ec Mon Sep 17 00:00:00 2001 From: Richard Quaicoe Date: Wed, 15 Jul 2026 13:09:10 +0000 Subject: [PATCH] fix: Fixed Python 3.14 threadpool compatility issue with daemon thread executor --- fastapi_taskflow/manager.py | 25 +++++++++++++++++++------ tests/test_executor.py | 14 ++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/fastapi_taskflow/manager.py b/fastapi_taskflow/manager.py index 906d374..8f4e340 100644 --- a/fastapi_taskflow/manager.py +++ b/fastapi_taskflow/manager.py @@ -236,14 +236,27 @@ def weakref_cb(_, q=self._work_queue): num_threads = len(self._threads) if num_threads < self._max_workers: - t = threading.Thread( - target=_cft._worker, - args=( + create_worker_context = getattr(self, "_create_worker_context", None) + worker_args: tuple[Any, ...] + if callable(create_worker_context): + worker_ctx = create_worker_context() + worker_args = ( + weakref.ref(self, weakref_cb), + worker_ctx, + self._work_queue, + ) + else: + worker_args = ( weakref.ref(self, weakref_cb), self._work_queue, - self._initializer, - self._initargs, - ), + getattr(self, "_initializer", None), + getattr(self, "_initargs", ()), + ) + + t = threading.Thread( + name=f"{self._thread_name_prefix or self}_{num_threads}", + target=_cft._worker, + args=worker_args, ) t.daemon = True t.start() diff --git a/tests/test_executor.py b/tests/test_executor.py index d00d5db..1215048 100644 --- a/tests/test_executor.py +++ b/tests/test_executor.py @@ -1,4 +1,5 @@ from fastapi_taskflow.executor import execute_task +from fastapi_taskflow.manager import _DaemonThreadPoolExecutor from fastapi_taskflow.models import TaskConfig, TaskStatus from fastapi_taskflow.store import TaskStore @@ -41,6 +42,19 @@ def func(x, y, z=0): assert captured == [(1, 2, 3)] +def test_daemon_thread_pool_executor_adjusts_without_initializer_attributes(): + executor = _DaemonThreadPoolExecutor(max_workers=1) + + for attr in ("_initializer", "_initargs"): + if hasattr(executor, attr): + delattr(executor, attr) + + executor._adjust_thread_count() + + assert len(executor._threads) == 1 + executor.shutdown(wait=True, cancel_futures=True) + + # --------------------------------------------------------------------------- # Async tasks # ---------------------------------------------------------------------------