28 lines
892 B
Python
28 lines
892 B
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
# Shared executor for CPU-bound analytics (pandas/sklearn) and sync MSSQL I/O
|
|
# (pyodbc is inherently synchronous and blocks the event loop if called directly).
|
|
#
|
|
# Workers are capped at 8 to avoid overwhelming the MSSQL connection pools.
|
|
# In K8s: set ANALYTICS_WORKERS to match the pod's CPU limit.
|
|
_WORKERS = min(8, int(os.environ.get("ANALYTICS_WORKERS", "0")) or (os.cpu_count() or 2) * 2)
|
|
|
|
_executor: ThreadPoolExecutor | None = None
|
|
|
|
|
|
def get_executor() -> ThreadPoolExecutor:
|
|
global _executor
|
|
if _executor is None:
|
|
_executor = ThreadPoolExecutor(max_workers=_WORKERS, thread_name_prefix="analytics")
|
|
return _executor
|
|
|
|
|
|
def shutdown_executor() -> None:
|
|
global _executor
|
|
if _executor is not None:
|
|
_executor.shutdown(wait=False)
|
|
_executor = None
|