Source code for core.dependency_guards

"""Timeout / fallback wrappers for optional external dependencies.

:func:`guard_async_dependency` runs a coroutine under an
:func:`asyncio.wait_for` timeout and returns a safe fallback value
(logging a warning) on timeout or error, while always re-raising
:class:`asyncio.CancelledError`. Used to keep a slow or unavailable
dependency (RAG, web search, …) from stalling the message pipeline.
"""

import asyncio
import logging
from typing import Any, Coroutine

logger = logging.getLogger(__name__)

[docs] async def guard_async_dependency( coro: Coroutine[Any, Any, Any], timeout_seconds: float, fallback_value: Any, service_name: str ) -> Any: """Run a coroutine under a timeout, returning a fallback instead of failing. Awaits *coro* inside :func:`asyncio.wait_for` so a slow or unavailable optional dependency (RAG, web search, an external API, etc.) cannot stall the message pipeline. On timeout it logs a warning and returns *fallback_value*; on any other exception it logs an error (with traceback) and likewise returns the fallback. :class:`asyncio.CancelledError` is deliberately re-raised so task cancellation is never swallowed. The only side effect is a log line via this module's ``logger``. Called wherever a non-critical async dependency is invoked along the hot path; also covered directly by ``tests/core/migration/test_dependency_guards.py``. Args: coro: The coroutine to await under the timeout. It is consumed exactly once whether or not it completes in time. timeout_seconds: Maximum seconds to wait before falling back. fallback_value: Value returned on timeout or error. service_name: Label for the guarded dependency, used in log messages. Returns: Any: The coroutine's result on success, otherwise *fallback_value*. Raises: asyncio.CancelledError: Always re-raised; cancellation is never caught. """ try: return await asyncio.wait_for(coro, timeout=timeout_seconds) except asyncio.TimeoutError: logger.warning( f"dependency_timeout service={service_name} timeout_s={timeout_seconds} fallback=True" ) return fallback_value except asyncio.CancelledError: # Never swallow cancellation raise except Exception as e: logger.error( f"dependency_failure service={service_name} error={str(e)} fallback=True", exc_info=True ) return fallback_value