"""Thread-local ClickHouse cache pool (DRY consolidation).

Provides a single ``OpenDeviationBarCache`` per thread, eliminating
per-call connection overhead (urllib3.PoolManager with 20 fds each).

Pattern proven in ``scripts/repair_direct_parquet.py`` at 24 workers
and used identically by kintsugi (Issue #279).
"""

from __future__ import annotations

import contextlib
import threading
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from opendeviationbar.clickhouse.cache import OpenDeviationBarCache

_thread_local = threading.local()


def get_thread_local_cache() -> OpenDeviationBarCache:
    """Get or create a thread-local OpenDeviationBarCache.

    Each worker thread gets ONE cache for its lifetime, eliminating
    per-call connection overhead (urllib3.PoolManager with 20 fds each).
    """
    cache = getattr(_thread_local, "cache", None)
    if cache is None:
        from opendeviationbar.clickhouse.cache import OpenDeviationBarCache

        _thread_local.cache = OpenDeviationBarCache()
        cache = _thread_local.cache
    return cache


def close_thread_local_cache() -> None:
    """Close and discard the thread-local cache (called at shutdown)."""
    cache = getattr(_thread_local, "cache", None)
    if cache is not None:
        with contextlib.suppress(Exception):
            cache.close()
        _thread_local.cache = None
