"""Shared thread pool for CPU-bound search (ROADMAP #85, tranche 5). Holder extrait de :mod:`backend.main` sans changement de comportement : un seul pool (2 workers, préfixe ``"search"``) créé au démarrage et arrêté à l'extinction par le lifespan de ``main``. Les routers et les endpoints restants y accèdent via :func:`get_search_executor` au lieu du global de ``main`` (plus d'import circulaire potentiel). """ from __future__ import annotations from concurrent.futures import ThreadPoolExecutor _executor: ThreadPoolExecutor | None = None def init_search_executor(max_workers: int = 2) -> ThreadPoolExecutor: """Create (or reuse) the shared search thread pool.""" global _executor if _executor is None: _executor = ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="search") return _executor def shutdown_search_executor() -> None: """Stop the shared search thread pool (best-effort, non-blocking).""" global _executor if _executor is not None: _executor.shutdown(wait=False) _executor = None def get_search_executor() -> ThreadPoolExecutor | None: """Return the shared search thread pool (``None`` before startup).""" return _executor