fix(ollama): cooldown provider health probes
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"""
|
||||
Lightweight in-process cooldown for noisy Ollama endpoint failures.
|
||||
|
||||
This does not change ADR-110 policy order. It only suppresses endpoints that
|
||||
just failed for short-lived high-volume callers such as embedding/RAG, while
|
||||
leaving health checks and failover status free to probe the full topology.
|
||||
This does not change ADR-110 policy order. It suppresses endpoints that just
|
||||
failed for short-lived callers while still returning explicit offline/cooldown
|
||||
state to health and route-status surfaces.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -60,6 +60,26 @@ def is_ollama_endpoint_blocked(url: str, *, now: float | None = None) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def get_ollama_endpoint_cooldown_remaining_seconds(
|
||||
url: str,
|
||||
*,
|
||||
now: float | None = None,
|
||||
) -> float:
|
||||
"""Return remaining cooldown seconds for display/debug surfaces."""
|
||||
if not url:
|
||||
return 0.0
|
||||
current_time = time.monotonic() if now is None else now
|
||||
normalized = _normalize_url(url)
|
||||
blocked_until = _blocked_until_by_url.get(normalized)
|
||||
if blocked_until is None:
|
||||
return 0.0
|
||||
remaining = blocked_until - current_time
|
||||
if remaining <= 0:
|
||||
_blocked_until_by_url.pop(normalized, None)
|
||||
return 0.0
|
||||
return remaining
|
||||
|
||||
|
||||
def filter_ollama_urls_with_cooldown(
|
||||
urls: Iterable[str],
|
||||
*,
|
||||
|
||||
@@ -29,6 +29,11 @@ import httpx
|
||||
import structlog
|
||||
|
||||
from src.core.config import get_settings
|
||||
from src.services.ollama_endpoint_circuit_breaker import (
|
||||
get_ollama_endpoint_cooldown_remaining_seconds,
|
||||
record_ollama_endpoint_failure,
|
||||
record_ollama_endpoint_success,
|
||||
)
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
@@ -206,9 +211,21 @@ class OllamaHealthMonitor:
|
||||
|
||||
async def _run_checks(self, host: str) -> HealthReport:
|
||||
"""依序執行三層檢查"""
|
||||
cooldown_remaining = get_ollama_endpoint_cooldown_remaining_seconds(host)
|
||||
if cooldown_remaining > 0:
|
||||
return HealthReport(
|
||||
status=HealthStatus.OFFLINE,
|
||||
host=host,
|
||||
reason=(
|
||||
"recent_endpoint_failure_cooldown:"
|
||||
f"{cooldown_remaining:.0f}s"
|
||||
),
|
||||
)
|
||||
|
||||
# 層 1:連通性
|
||||
connectivity_ok = await self._check_connectivity(host)
|
||||
if not connectivity_ok:
|
||||
record_ollama_endpoint_failure(host)
|
||||
return HealthReport(
|
||||
status=HealthStatus.OFFLINE,
|
||||
host=host,
|
||||
@@ -217,6 +234,7 @@ class OllamaHealthMonitor:
|
||||
|
||||
# 層 2:推理測試
|
||||
report = await self._check_inference(host)
|
||||
record_ollama_endpoint_success(host)
|
||||
return report
|
||||
|
||||
async def _check_connectivity(self, host: str) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user