From cb37d397bf3518a8965847ea8e61a38c6e0604f2 Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Tue, 7 Jul 2026 12:05:21 +0530 Subject: [PATCH 01/11] resolve merge conflict --- backend/app/core/config.py | 4 + backend/app/services/health_probes.py | 219 ++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 backend/app/services/health_probes.py diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 8c39ca043..8d8d79f24 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -190,6 +190,10 @@ def AWS_S3_BUCKET(self) -> str: EVAL_FAST_STALL_THRESHOLD_MINUTES: int = 15 PENDING_JOB_QUERY_TIMEOUT_MS: int = 1000 + HEALTH_PROBE_ORG_ID: int | None = None + HEALTH_PROBE_PROJECT_ID: int | None = None + HEALTH_PROBE_INTERVAL_MINUTES: int = 5 + # AI-assisted prompt improvement settings. # See docs/srd-ai-prompt-improvement.md for the full design rationale. # Platform-owned Anthropic key shared by every org/project for this feature, diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py new file mode 100644 index 000000000..d5f3ec70f --- /dev/null +++ b/backend/app/services/health_probes.py @@ -0,0 +1,219 @@ +import base64 +import logging +import time +from concurrent.futures import ThreadPoolExecutor +from dataclasses import dataclass +from typing import Any, Literal + +from sqlmodel import Session + +from app.core.audio_utils import AudioRef +from app.core.config import settings +from app.models.llm import KaapiCompletionConfig, QueryParams +from app.services.llm.providers.base import BaseProvider +from app.services.llm.providers.registry import get_llm_provider + +logger = logging.getLogger(__name__) + +_PROBE_INPUT = "ping" +_PROBE_MAX_TOKENS = 1 +_PROBE_WORKERS = 4 + +# "Hello" ~1sec +_STT_AUDIO_B64: str = "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" +_STT_AUDIO_MIME: str = "audio/ogg" + + +Modality = Literal["text", "tts", "stt"] + + +@dataclass(frozen=True) +class Probe: + provider: str + model: str + modality: Modality + + +_PROBES: list[Probe] = [ + # Text + Probe(provider="openai", model="gpt-4o-mini", modality="text"), + Probe(provider="google", model="gemini-2.5-flash", modality="text"), + Probe(provider="google-aistudio", model="gemini-2.5-flash", modality="text"), + Probe(provider="anthropic", model="claude-3-5-haiku-latest", modality="text"), + Probe(provider="sarvamai", model="sarvam-m", modality="text"), + # TTS + Probe(provider="openai", model="tts-1", modality="tts"), + Probe(provider="google", model="gemini-2.5-flash-preview-tts", modality="tts"), + Probe(provider="sarvamai", model="bulbul:v2", modality="tts"), + Probe(provider="elevenlabs", model="eleven_flash_v2_5", modality="tts"), + # STT + Probe(provider="openai", model="whisper-1", modality="stt"), + Probe(provider="google", model="gemini-2.5-pro", modality="stt"), + Probe(provider="sarvamai", model="saarika:v2.5", modality="stt"), + Probe(provider="elevenlabs", model="scribe_v1", modality="stt"), +] + + +def _build_provider( + session: Session, probe: Probe, *, org_id: int, project_id: int +) -> BaseProvider | None: + try: + return get_llm_provider( + session=session, + provider_type=probe.provider, + project_id=project_id, + organization_id=org_id, + ) + except (ValueError, RuntimeError) as e: + logger.warning( + f"[_build_provider] Client init failed | provider: {probe.provider}, " + f"modality: {probe.modality}, error: {e}" + ) + return None + + +def _build_config_and_input( + probe: Probe, +) -> tuple[KaapiCompletionConfig, str | AudioRef] | None: + if probe.modality == "text": + cfg = KaapiCompletionConfig.model_validate( + { + "provider": probe.provider, + "type": "text", + "params": { + "model": probe.model, + "temperature": 0.0, + "max_output_tokens": _PROBE_MAX_TOKENS, + }, + } + ) + return cfg, _PROBE_INPUT + + if probe.modality == "tts": + cfg = KaapiCompletionConfig.model_validate( + { + "provider": probe.provider, + "type": "tts", + "params": {"model": probe.model}, + } + ) + return cfg, _PROBE_INPUT + + # stt + if not _STT_AUDIO_B64: + return None + cfg = KaapiCompletionConfig.model_validate( + { + "provider": probe.provider, + "type": "stt", + "params": {"model": probe.model}, + } + ) + audio = AudioRef( + bytes_=base64.b64decode(_STT_AUDIO_B64), + mime_type=_STT_AUDIO_MIME, + ) + return cfg, audio + + +def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: + result: dict[str, Any] = { + "endpoint": "llm/call", + "provider": probe.provider, + "modality": probe.modality, + "model": probe.model, + "ok": False, + "latency_ms": None, + "error": None, + } + if provider is None: + result["error"] = "client_init_failed" + return result + + built = _build_config_and_input(probe) + if built is None: + result["error"] = "stt_audio_not_configured" + return result + config, resolved_input = built + query = QueryParams(input=_PROBE_INPUT if isinstance(resolved_input, str) else "") + + started = time.perf_counter() + try: + response, error = provider.execute( + completion_config=config, # type: ignore[arg-type] + query=query, + resolved_input=resolved_input, + ) + except Exception as e: + result["latency_ms"] = int((time.perf_counter() - started) * 1000) + result["error"] = f"{type(e).__name__}: {e}" + logger.warning( + f"[_run_probe] Raised | provider: {probe.provider}, " + f"modality: {probe.modality}, error: {result['error']}" + ) + return result + + result["latency_ms"] = int((time.perf_counter() - started) * 1000) + if response is None: + result["error"] = error or "no_response" + logger.warning( + f"[_run_probe] Failed | provider: {probe.provider}, " + f"modality: {probe.modality}, error: {result['error']}" + ) + return result + + result["ok"] = True + return result + + +def run_probes(*, session: Session) -> dict[str, Any]: + org_id = settings.HEALTH_PROBE_ORG_ID + project_id = settings.HEALTH_PROBE_PROJECT_ID + if org_id is None or project_id is None: + logger.warning( + "[run_probes] Health probe org/project not configured — skipping" + ) + return {"skipped": True, "reason": "health_probe_org_or_project_not_set"} + + logger.info( + f"[run_probes] Starting | probes: {len(_PROBES)}, " + f"org_id: {org_id}, project_id: {project_id}" + ) + + provider_cache: dict[str, BaseProvider | None] = {} + for p in _PROBES: + if p.provider not in provider_cache: + provider_cache[p.provider] = _build_provider( + session, p, org_id=org_id, project_id=project_id + ) + dispatch = [(p, provider_cache[p.provider]) for p in _PROBES] + + started = time.perf_counter() + with ThreadPoolExecutor(max_workers=_PROBE_WORKERS) as pool: + results = list(pool.map(lambda pp: _run_probe(pp[1], pp[0]), dispatch)) + elapsed_ms = int((time.perf_counter() - started) * 1000) + + ok_count = sum(1 for r in results if r["ok"]) + logger.info( + f"[run_probes] Completed | total: {len(results)}, ok: {ok_count}, " + f"failed: {len(results) - ok_count}, elapsed_ms: {elapsed_ms}" + ) + return { + "elapsed_ms": elapsed_ms, + "total": len(results), + "ok": ok_count, + "failed": len(results) - ok_count, + "results": results, + } + + +if __name__ == "__main__": + assert _PROBES, "probe list must not be empty" + modalities = {p.modality for p in _PROBES} + assert modalities == {"text", "tts", "stt"}, modalities + for probe in _PROBES: + if probe.modality == "stt" and not _STT_AUDIO_B64: + continue + built = _build_config_and_input(probe) + assert built is not None + print("ok") From 8e50f5624bac6a4798e86dedf8a3cc834f27f0df Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Thu, 9 Jul 2026 12:30:35 +0530 Subject: [PATCH 02/11] fix logger from warn to error --- backend/app/api/routes/cron.py | 32 +++++++++++++++++++++-- backend/app/celery/tasks/job_execution.py | 17 ++++++++++++ backend/app/core/telemetry.py | 8 ++++-- backend/app/services/health_probes.py | 10 +++---- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/backend/app/api/routes/cron.py b/backend/app/api/routes/cron.py index c31288ce8..b1e696b31 100644 --- a/backend/app/api/routes/cron.py +++ b/backend/app/api/routes/cron.py @@ -7,6 +7,7 @@ from app.api.deps import SessionDep from app.api.permissions import Permission, require_permission from app.core.config import settings +from app.celery.tasks.job_execution import run_health_probes from app.crud.evaluations import process_all_pending_evaluations from app.services.job_monitoring import monitor_pending_jobs @@ -15,13 +16,11 @@ router = APIRouter(tags=["Cron"]) EVALUATION_CRON_MONITOR_CONFIG: MonitorConfig = { - # Expected cadence: a check-in every CRON_INTERVAL_MINUTES minutes. "schedule": { "type": "interval", "value": settings.CRON_INTERVAL_MINUTES, "unit": "minute", }, - # Timezone for the schedule (only affects crontab-style schedules). "timezone": "UTC", # Grace period (minutes) before a late check-in is marked as missed. "checkin_margin": 2, @@ -33,6 +32,20 @@ "recovery_threshold": 1, } +HEALTH_PROBES_CRON_MONITOR_CONFIG: MonitorConfig = { + "schedule": { + "type": "interval", + # not required eventbridge is aleady 5 mins. So not required. + "value": settings.HEALTH_PROBE_INTERVAL_MINUTES, + "unit": "minute", + }, + "timezone": "UTC", + "checkin_margin": 2, + "max_runtime": 2 * settings.HEALTH_PROBE_INTERVAL_MINUTES, + "failure_issue_threshold": 2, + "recovery_threshold": 1, +} + PENDING_JOBS_CRON_MONITOR_CONFIG: MonitorConfig = { "schedule": { "type": "interval", @@ -123,6 +136,21 @@ async def evaluation_cron_job( raise +@router.get( + "/cron/health-probes", + include_in_schema=False, + dependencies=[Depends(require_permission(Permission.SUPERUSER))], +) +@sentry_sdk.monitor( + monitor_slug="health-probes-cron-job", + monitor_config=HEALTH_PROBES_CRON_MONITOR_CONFIG, +) +def health_probes_cron_job() -> dict: + logger.info("[health_probes_cron_job] Cron job invoked — enqueueing task") + async_result = run_health_probes.delay() + return {"enqueued": True, "task_id": async_result.id} + + @router.get( "/cron/pending-jobs", include_in_schema=False, diff --git a/backend/app/celery/tasks/job_execution.py b/backend/app/celery/tasks/job_execution.py index 0a6320612..c8802c5a9 100644 --- a/backend/app/celery/tasks/job_execution.py +++ b/backend/app/celery/tasks/job_execution.py @@ -406,6 +406,23 @@ def run_evaluation_fast_aggregate( ) +@celery_app.task(bind=True, queue="default", priority=2) +@gevent_timeout(settings.CELERY_TASK_SOFT_TIME_LIMIT, "run_health_probes") +def run_health_probes(self, trace_id: str = DEFAULT_TRACE_ID) -> dict: + from sqlmodel import Session + + from app.core.db import engine + from app.services.health_probes import run_probes + + _set_trace(trace_id) + + def _do() -> dict: + with Session(engine) as session: + return run_probes(session=session) + + return _run_with_otel_parent(self, _do) + + @celery_app.task(bind=True, queue="default", priority=1) @gevent_timeout( settings.CELERY_TASK_SOFT_TIME_LIMIT, "send_eval_completion_notification" diff --git a/backend/app/core/telemetry.py b/backend/app/core/telemetry.py index 99d2fc959..95f64f13f 100644 --- a/backend/app/core/telemetry.py +++ b/backend/app/core/telemetry.py @@ -190,11 +190,15 @@ def setup_telemetry(service_name: str | None = None) -> None: resource = _build_resource(service_name) tracer_provider = TracerProvider(resource=resource) - # Bridge OTel spans into Sentry as Sentry transactions and spans, with full attribute and error capture. if settings.SENTRY_DSN: - from sentry_sdk.integrations.opentelemetry import SentrySpanProcessor + from opentelemetry.propagate import set_global_textmap + from sentry_sdk.integrations.opentelemetry import ( + SentryPropagator, + SentrySpanProcessor, + ) tracer_provider.add_span_processor(SentrySpanProcessor()) + set_global_textmap(SentryPropagator()) trace.set_tracer_provider(tracer_provider) diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index d5f3ec70f..598019d94 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -36,14 +36,14 @@ class Probe: _PROBES: list[Probe] = [ # Text - Probe(provider="openai", model="gpt-4o-mini", modality="text"), + Probe(provider="openai", model="gpt-4o-1-mini", modality="text"), Probe(provider="google", model="gemini-2.5-flash", modality="text"), Probe(provider="google-aistudio", model="gemini-2.5-flash", modality="text"), Probe(provider="anthropic", model="claude-3-5-haiku-latest", modality="text"), Probe(provider="sarvamai", model="sarvam-m", modality="text"), # TTS Probe(provider="openai", model="tts-1", modality="tts"), - Probe(provider="google", model="gemini-2.5-flash-preview-tts", modality="tts"), + Probe(provider="google", model="gemini-2.5-flash-preview-ttsss", modality="tts"), Probe(provider="sarvamai", model="bulbul:v2", modality="tts"), Probe(provider="elevenlabs", model="eleven_flash_v2_5", modality="tts"), # STT @@ -65,7 +65,7 @@ def _build_provider( organization_id=org_id, ) except (ValueError, RuntimeError) as e: - logger.warning( + logger.error( f"[_build_provider] Client init failed | provider: {probe.provider}, " f"modality: {probe.modality}, error: {e}" ) @@ -147,7 +147,7 @@ def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: except Exception as e: result["latency_ms"] = int((time.perf_counter() - started) * 1000) result["error"] = f"{type(e).__name__}: {e}" - logger.warning( + logger.error( f"[_run_probe] Raised | provider: {probe.provider}, " f"modality: {probe.modality}, error: {result['error']}" ) @@ -156,7 +156,7 @@ def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: result["latency_ms"] = int((time.perf_counter() - started) * 1000) if response is None: result["error"] = error or "no_response" - logger.warning( + logger.error( f"[_run_probe] Failed | provider: {probe.provider}, " f"modality: {probe.modality}, error: {result['error']}" ) From d74e2344a1c0c6055632c76e3e93f804e9dd6b91 Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Thu, 9 Jul 2026 16:50:35 +0530 Subject: [PATCH 03/11] chore: remove error logging from creds error --- backend/app/services/health_probes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index 598019d94..63872e5fe 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -65,7 +65,7 @@ def _build_provider( organization_id=org_id, ) except (ValueError, RuntimeError) as e: - logger.error( + logger.warning( f"[_build_provider] Client init failed | provider: {probe.provider}, " f"modality: {probe.modality}, error: {e}" ) From a077ef15c661ebb18553b8db9376e86a903b009c Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Thu, 9 Jul 2026 16:57:12 +0530 Subject: [PATCH 04/11] add health-probes to the list of cron endpoints --- scripts/python/invoke-cron.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/python/invoke-cron.py b/scripts/python/invoke-cron.py index 64df37b25..64b409573 100644 --- a/scripts/python/invoke-cron.py +++ b/scripts/python/invoke-cron.py @@ -18,6 +18,7 @@ ENDPOINTS = [ "/api/v1/cron/evaluations", "/api/v1/cron/pending-jobs", + "/api/v1/cron/health-probes", ] REQUEST_TIMEOUT = 30 # Timeout for requests in seconds From cdc3ac6650aa9fd592c97cd61f346b4ac4fc8d9f Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Fri, 10 Jul 2026 09:47:52 +0530 Subject: [PATCH 05/11] feat: add more models and test cases --- backend/app/services/health_probes.py | 23 +- .../api/routes/test_cron_health_probes.py | 65 +++++ .../tests/celery/test_run_health_probes.py | 90 +++++++ .../app/tests/services/test_health_probes.py | 244 ++++++++++++++++++ 4 files changed, 411 insertions(+), 11 deletions(-) create mode 100644 backend/app/tests/api/routes/test_cron_health_probes.py create mode 100644 backend/app/tests/celery/test_run_health_probes.py create mode 100644 backend/app/tests/services/test_health_probes.py diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index 63872e5fe..792c1ce1f 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -36,21 +36,22 @@ class Probe: _PROBES: list[Probe] = [ # Text - Probe(provider="openai", model="gpt-4o-1-mini", modality="text"), + Probe(provider="openai", model="gpt-4o-mini", modality="text"), Probe(provider="google", model="gemini-2.5-flash", modality="text"), - Probe(provider="google-aistudio", model="gemini-2.5-flash", modality="text"), - Probe(provider="anthropic", model="claude-3-5-haiku-latest", modality="text"), - Probe(provider="sarvamai", model="sarvam-m", modality="text"), + Probe(provider="google", model="gemini-2.5-flash", modality="text"), + Probe(provider="google", model="gemini-2.5-pro", modality="text"), # TTS - Probe(provider="openai", model="tts-1", modality="tts"), - Probe(provider="google", model="gemini-2.5-flash-preview-ttsss", modality="tts"), - Probe(provider="sarvamai", model="bulbul:v2", modality="tts"), - Probe(provider="elevenlabs", model="eleven_flash_v2_5", modality="tts"), + Probe(provider="google", model="gemini-2.5-flash-preview-tts", modality="tts"), + Probe(provider="google", model="gemini-3.1-flash-preview-tts", modality="tts"), + Probe(provider="google", model="gemini-2.5-pro-preview-tts", modality="tts"), + Probe(provider="sarvamai", model="bulbul:v3", modality="tts"), + Probe(provider="elevenlabs", model="eleven_v3", modality="tts"), # STT - Probe(provider="openai", model="whisper-1", modality="stt"), Probe(provider="google", model="gemini-2.5-pro", modality="stt"), - Probe(provider="sarvamai", model="saarika:v2.5", modality="stt"), - Probe(provider="elevenlabs", model="scribe_v1", modality="stt"), + Probe(provider="google", model="gemini-2.5-flash", modality="stt"), + Probe(provider="google", model="gemini-3.1-pro-preview", modality="stt"), + Probe(provider="sarvamai", model="saaras:v3", modality="stt"), + Probe(provider="elevenlabs", model="scribe_v2", modality="stt"), ] diff --git a/backend/app/tests/api/routes/test_cron_health_probes.py b/backend/app/tests/api/routes/test_cron_health_probes.py new file mode 100644 index 000000000..00f1f0cb1 --- /dev/null +++ b/backend/app/tests/api/routes/test_cron_health_probes.py @@ -0,0 +1,65 @@ +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +from fastapi.testclient import TestClient + +from app.core.config import settings +from app.tests.utils.auth import TestAuthContext + + +def test_health_probes_cron_enqueues_and_returns_task_id( + client: TestClient, + superuser_api_key: TestAuthContext, +) -> None: + fake_async_result = SimpleNamespace(id="test-task-id") + + with patch( + "app.api.routes.cron.run_health_probes.delay", + return_value=fake_async_result, + ) as delay_mock: + response = client.get( + f"{settings.API_V1_STR}/cron/health-probes", + headers={"X-API-KEY": superuser_api_key.key}, + ) + + assert response.status_code == 200 + assert response.json() == {"enqueued": True, "task_id": "test-task-id"} + delay_mock.assert_called_once_with() + + +def test_health_probes_cron_requires_superuser( + client: TestClient, + user_api_key: TestAuthContext, +) -> None: + with patch( + "app.api.routes.cron.run_health_probes.delay", + return_value=SimpleNamespace(id="should-not-run"), + ) as delay_mock: + response = client.get( + f"{settings.API_V1_STR}/cron/health-probes", + headers={"X-API-KEY": user_api_key.key}, + ) + + assert response.status_code == 403 + assert "Insufficient permissions" in response.json()["error"] + delay_mock.assert_not_called() + + +def test_health_probes_cron_requires_authentication( + client: TestClient, +) -> None: + with patch( + "app.api.routes.cron.run_health_probes.delay", + return_value=SimpleNamespace(id="should-not-run"), + ) as delay_mock: + response = client.get(f"{settings.API_V1_STR}/cron/health-probes") + + assert response.status_code in (401, 403) + delay_mock.assert_not_called() + + +def test_health_probes_cron_not_in_openapi_schema(client: TestClient) -> None: + response = client.get(f"{settings.API_V1_STR}/openapi.json") + assert response.status_code == 200 + paths = response.json().get("paths", {}) + assert f"{settings.API_V1_STR}/cron/health-probes" not in paths diff --git a/backend/app/tests/celery/test_run_health_probes.py b/backend/app/tests/celery/test_run_health_probes.py new file mode 100644 index 000000000..8c38faaa9 --- /dev/null +++ b/backend/app/tests/celery/test_run_health_probes.py @@ -0,0 +1,90 @@ +from unittest.mock import patch + +from sqlmodel import Session + +from app.celery.tasks import job_execution + + +class _NonClosingSession: + """Wrapper so the task's `with Session(engine)` uses the transactional + conftest session and doesn't close it.""" + + def __init__(self, session: Session): + self._session = session + + def __enter__(self) -> Session: + return self._session + + def __exit__(self, exc_type, exc, tb) -> bool: + return False + + +def test_run_health_probes_task_returns_run_probes_result(db: Session): + canned = { + "elapsed_ms": 42, + "total": 3, + "ok": 3, + "failed": 0, + "results": [ + { + "endpoint": "llm/call", + "provider": "openai", + "modality": "text", + "model": "gpt-4o-1-mini", + "ok": True, + "latency_ms": 10, + "error": None, + } + ], + } + + captured: dict = {} + + def _fake_run_probes(*, session: Session) -> dict: + captured["session"] = session + return canned + + with ( + patch( + "app.services.health_probes.run_probes", + side_effect=_fake_run_probes, + ), + patch( + "app.core.db.engine", + new=object(), # engine is only fed to Session() which we intercept below + ), + patch( + "sqlmodel.Session", + side_effect=lambda _engine: _NonClosingSession(db), + ), + ): + result = job_execution.run_health_probes.apply(args=[]).get() + + assert result == canned + assert captured["session"] is db + + +def test_run_health_probes_task_skipped_when_settings_unset(db: Session): + """When run_probes reports skipped, the task returns the skip payload verbatim.""" + skipped = { + "skipped": True, + "reason": "health_probe_org_or_project_not_set", + } + + with ( + patch( + "app.services.health_probes.run_probes", + return_value=skipped, + ), + patch( + "app.core.db.engine", + new=object(), + ), + patch( + "sqlmodel.Session", + side_effect=lambda _engine: _NonClosingSession(db), + ), + ): + result = job_execution.run_health_probes.apply(args=[]).get() + + assert result == skipped diff --git a/backend/app/tests/services/test_health_probes.py b/backend/app/tests/services/test_health_probes.py new file mode 100644 index 000000000..8d6f83c7b --- /dev/null +++ b/backend/app/tests/services/test_health_probes.py @@ -0,0 +1,244 @@ +from unittest.mock import MagicMock, patch + +import pytest +from sqlmodel import Session + +from app.core.config import settings +from app.services import health_probes +from app.services.health_probes import _PROBES, run_probes + + +class _FakeProvider: + """Minimal BaseProvider stand-in whose execute() returns a canned tuple.""" + + def __init__(self, response=None, error=None, raise_exc: Exception | None = None): + self._response = response + self._error = error + self._raise_exc = raise_exc + self.calls: list[dict] = [] + + def execute(self, *, completion_config, query, resolved_input): + self.calls.append( + { + "completion_config": completion_config, + "query": query, + "resolved_input": resolved_input, + } + ) + if self._raise_exc is not None: + raise self._raise_exc + return self._response, self._error + + +@pytest.fixture +def configured_probe_settings(monkeypatch): + monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", 1) + monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", 1) + + +class TestSkipWhenNotConfigured: + def test_returns_skipped_when_org_id_missing(self, db: Session, monkeypatch): + monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", None) + monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", 1) + + called = {"n": 0} + + def _tracker(**_kwargs): + called["n"] += 1 + return _FakeProvider(response={"ok": True}) + + monkeypatch.setattr(health_probes, "get_llm_provider", _tracker) + + result = run_probes(session=db) + + assert result == { + "skipped": True, + "reason": "health_probe_org_or_project_not_set", + } + assert called["n"] == 0 + + def test_returns_skipped_when_project_id_missing(self, db: Session, monkeypatch): + monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", 1) + monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", None) + monkeypatch.setattr( + health_probes, + "get_llm_provider", + lambda **_k: pytest.fail("provider must not be built"), + ) + + result = run_probes(session=db) + + assert result["skipped"] is True + assert result["reason"] == "health_probe_org_or_project_not_set" + + +class TestRunProbesShape: + def test_all_probes_ok_returns_expected_structure( + self, db: Session, monkeypatch, configured_probe_settings + ): + fake = _FakeProvider(response={"data": "pong"}, error=None) + monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) + + result = run_probes(session=db) + + assert set(result.keys()) == { + "elapsed_ms", + "total", + "ok", + "failed", + "results", + } + assert isinstance(result["elapsed_ms"], int) + assert result["total"] == len(_PROBES) + assert result["ok"] == len(_PROBES) + assert result["failed"] == 0 + assert len(result["results"]) == len(_PROBES) + + for r in result["results"]: + assert set(r.keys()) == { + "endpoint", + "provider", + "modality", + "model", + "ok", + "latency_ms", + "error", + } + assert r["endpoint"] == "llm/call" + assert r["ok"] is True + assert r["error"] is None + assert isinstance(r["latency_ms"], int) + + +class TestProviderInitFailure: + def test_get_llm_provider_value_error_marks_client_init_failed( + self, db: Session, monkeypatch, configured_probe_settings + ): + def _boom(**_kwargs): + raise ValueError("no creds") + + monkeypatch.setattr(health_probes, "get_llm_provider", _boom) + + result = run_probes(session=db) + + assert result["ok"] == 0 + assert result["failed"] == len(_PROBES) + for r in result["results"]: + assert r["ok"] is False + assert r["error"] == "client_init_failed" + assert r["latency_ms"] is None + + def test_get_llm_provider_runtime_error_marks_client_init_failed( + self, db: Session, monkeypatch, configured_probe_settings + ): + monkeypatch.setattr( + health_probes, + "get_llm_provider", + lambda **_k: (_ for _ in ()).throw(RuntimeError("bad")), + ) + + result = run_probes(session=db) + + assert result["failed"] == len(_PROBES) + assert all(r["error"] == "client_init_failed" for r in result["results"]) + assert all(r["latency_ms"] is None for r in result["results"]) + + +class TestExecuteBehaviors: + def test_execute_raises_marks_error_with_exception_class_name( + self, db: Session, monkeypatch, configured_probe_settings + ): + fake = _FakeProvider(raise_exc=TimeoutError("slow")) + monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) + + result = run_probes(session=db) + + assert result["ok"] == 0 + for r in result["results"]: + assert r["ok"] is False + assert r["error"].startswith("TimeoutError") + assert "slow" in r["error"] + assert isinstance(r["latency_ms"], int) + + def test_provider_returns_none_response_uses_provided_error( + self, db: Session, monkeypatch, configured_probe_settings + ): + fake = _FakeProvider(response=None, error="some_error") + monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) + + result = run_probes(session=db) + + assert result["ok"] == 0 + assert result["failed"] == len(_PROBES) + for r in result["results"]: + assert r["ok"] is False + assert r["error"] == "some_error" + assert isinstance(r["latency_ms"], int) + + def test_provider_returns_none_response_and_no_error_defaults_no_response( + self, db: Session, monkeypatch, configured_probe_settings + ): + fake = _FakeProvider(response=None, error=None) + monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) + + result = run_probes(session=db) + + for r in result["results"]: + assert r["ok"] is False + assert r["error"] == "no_response" + + def test_provider_returns_response_marks_ok( + self, db: Session, monkeypatch, configured_probe_settings + ): + fake = _FakeProvider(response={"ok": 1}, error=None) + monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) + + result = run_probes(session=db) + + assert result["ok"] == len(_PROBES) + for r in result["results"]: + assert r["ok"] is True + assert r["error"] is None + + +class TestSttAudioNotConfigured: + def test_empty_stt_audio_short_circuits_stt_probes( + self, db: Session, monkeypatch, configured_probe_settings + ): + monkeypatch.setattr(health_probes, "_STT_AUDIO_B64", "") + fake = _FakeProvider(response={"ok": 1}, error=None) + monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) + + result = run_probes(session=db) + + stt_results = [r for r in result["results"] if r["modality"] == "stt"] + assert stt_results, "expected at least one STT probe" + for r in stt_results: + assert r["ok"] is False + assert r["error"] == "stt_audio_not_configured" + # short-circuit happens before execute → no latency recorded + assert r["latency_ms"] is None + + non_stt = [r for r in result["results"] if r["modality"] != "stt"] + for r in non_stt: + assert r["ok"] is True + + +class TestProviderCaching: + def test_get_llm_provider_called_once_per_unique_provider( + self, db: Session, monkeypatch, configured_probe_settings + ): + seen_providers: list[str] = [] + + def _factory(**kwargs): + seen_providers.append(kwargs["provider_type"]) + return _FakeProvider(response={"ok": 1}, error=None) + + monkeypatch.setattr(health_probes, "get_llm_provider", _factory) + + run_probes(session=db) + + unique_probe_providers = {p.provider for p in _PROBES} + # One factory call per unique provider name, not per probe + assert sorted(seen_providers) == sorted(unique_probe_providers) + assert len(seen_providers) < len(_PROBES) From 652b048aa32ef372c49a9e5b8de56eb43067a73b Mon Sep 17 00:00:00 2001 From: Prajna Prayas Date: Fri, 10 Jul 2026 09:57:15 +0530 Subject: [PATCH 06/11] Update backend/app/services/health_probes.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- backend/app/services/health_probes.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index 792c1ce1f..b73934c06 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -131,7 +131,19 @@ def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: result["error"] = "client_init_failed" return result - built = _build_config_and_input(probe) + if provider is None: + result["error"] = "client_init_failed" + return result + + try: + built = _build_config_and_input(probe) + except Exception as e: + result["error"] = f"{type(e).__name__}: {e}" + logger.error( + f"[_run_probe] Config build failed | provider: {probe.provider}, " + f"modality: {probe.modality}, error: {result['error']}" + ) + return result if built is None: result["error"] = "stt_audio_not_configured" return result From 23ab51e33d4f9bf1d8f161d922c1f74842a73ad8 Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Fri, 10 Jul 2026 09:58:36 +0530 Subject: [PATCH 07/11] fix: remove extra google got 2.5-flash --- backend/app/services/health_probes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index 792c1ce1f..df7d3b314 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -38,7 +38,6 @@ class Probe: # Text Probe(provider="openai", model="gpt-4o-mini", modality="text"), Probe(provider="google", model="gemini-2.5-flash", modality="text"), - Probe(provider="google", model="gemini-2.5-flash", modality="text"), Probe(provider="google", model="gemini-2.5-pro", modality="text"), # TTS Probe(provider="google", model="gemini-2.5-flash-preview-tts", modality="tts"), From 6c0a146e30d01565fdb7bf70ba3856c2ca10158e Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Fri, 10 Jul 2026 10:46:00 +0530 Subject: [PATCH 08/11] test cases --- backend/app/services/health_probes.py | 16 ---------------- .../tests/api/routes/test_cron_health_probes.py | 2 +- .../app/tests/celery/test_run_health_probes.py | 4 ---- backend/app/tests/services/test_health_probes.py | 4 ---- 4 files changed, 1 insertion(+), 25 deletions(-) diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index adf8a87ca..56d5b9ad7 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -130,10 +130,6 @@ def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: result["error"] = "client_init_failed" return result - if provider is None: - result["error"] = "client_init_failed" - return result - try: built = _build_config_and_input(probe) except Exception as e: @@ -217,15 +213,3 @@ def run_probes(*, session: Session) -> dict[str, Any]: "failed": len(results) - ok_count, "results": results, } - - -if __name__ == "__main__": - assert _PROBES, "probe list must not be empty" - modalities = {p.modality for p in _PROBES} - assert modalities == {"text", "tts", "stt"}, modalities - for probe in _PROBES: - if probe.modality == "stt" and not _STT_AUDIO_B64: - continue - built = _build_config_and_input(probe) - assert built is not None - print("ok") diff --git a/backend/app/tests/api/routes/test_cron_health_probes.py b/backend/app/tests/api/routes/test_cron_health_probes.py index 00f1f0cb1..b92b2ab25 100644 --- a/backend/app/tests/api/routes/test_cron_health_probes.py +++ b/backend/app/tests/api/routes/test_cron_health_probes.py @@ -1,5 +1,5 @@ from types import SimpleNamespace -from unittest.mock import MagicMock, patch +from unittest.mock import patch from fastapi.testclient import TestClient diff --git a/backend/app/tests/celery/test_run_health_probes.py b/backend/app/tests/celery/test_run_health_probes.py index 8c38faaa9..b7ebde3f1 100644 --- a/backend/app/tests/celery/test_run_health_probes.py +++ b/backend/app/tests/celery/test_run_health_probes.py @@ -6,9 +6,6 @@ class _NonClosingSession: - """Wrapper so the task's `with Session(engine)` uses the transactional - conftest session and doesn't close it.""" - def __init__(self, session: Session): self._session = session @@ -65,7 +62,6 @@ def _fake_run_probes(*, session: Session) -> dict: def test_run_health_probes_task_skipped_when_settings_unset(db: Session): - """When run_probes reports skipped, the task returns the skip payload verbatim.""" skipped = { "skipped": True, "reason": "health_probe_org_or_project_not_set", diff --git a/backend/app/tests/services/test_health_probes.py b/backend/app/tests/services/test_health_probes.py index 8d6f83c7b..d2a2e85a8 100644 --- a/backend/app/tests/services/test_health_probes.py +++ b/backend/app/tests/services/test_health_probes.py @@ -1,5 +1,3 @@ -from unittest.mock import MagicMock, patch - import pytest from sqlmodel import Session @@ -9,8 +7,6 @@ class _FakeProvider: - """Minimal BaseProvider stand-in whose execute() returns a canned tuple.""" - def __init__(self, response=None, error=None, raise_exc: Exception | None = None): self._response = response self._error = error From 1ebef3d5ac595ffe32121da0a18e90e8de7252d2 Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Wed, 29 Jul 2026 10:58:54 +0530 Subject: [PATCH 09/11] resolved all comments and test cases --- backend/app/api/routes/cron.py | 20 +- backend/app/assets/health_probe_hello.ogg | Bin 0 -> 15322 bytes backend/app/celery/tasks/job_execution.py | 13 +- backend/app/services/health_probes.py | 214 ++++++++++++---- .../tests/celery/test_run_health_probes.py | 82 +----- .../app/tests/services/test_health_probes.py | 240 ++++++++++++++---- 6 files changed, 366 insertions(+), 203 deletions(-) create mode 100644 backend/app/assets/health_probe_hello.ogg diff --git a/backend/app/api/routes/cron.py b/backend/app/api/routes/cron.py index b1e696b31..80c15f827 100644 --- a/backend/app/api/routes/cron.py +++ b/backend/app/api/routes/cron.py @@ -32,20 +32,6 @@ "recovery_threshold": 1, } -HEALTH_PROBES_CRON_MONITOR_CONFIG: MonitorConfig = { - "schedule": { - "type": "interval", - # not required eventbridge is aleady 5 mins. So not required. - "value": settings.HEALTH_PROBE_INTERVAL_MINUTES, - "unit": "minute", - }, - "timezone": "UTC", - "checkin_margin": 2, - "max_runtime": 2 * settings.HEALTH_PROBE_INTERVAL_MINUTES, - "failure_issue_threshold": 2, - "recovery_threshold": 1, -} - PENDING_JOBS_CRON_MONITOR_CONFIG: MonitorConfig = { "schedule": { "type": "interval", @@ -141,11 +127,9 @@ async def evaluation_cron_job( include_in_schema=False, dependencies=[Depends(require_permission(Permission.SUPERUSER))], ) -@sentry_sdk.monitor( - monitor_slug="health-probes-cron-job", - monitor_config=HEALTH_PROBES_CRON_MONITOR_CONFIG, -) def health_probes_cron_job() -> dict: + # Sentry check-ins happen inside the Celery task so the monitor reflects + # probe results, not just enqueue success. logger.info("[health_probes_cron_job] Cron job invoked — enqueueing task") async_result = run_health_probes.delay() return {"enqueued": True, "task_id": async_result.id} diff --git a/backend/app/assets/health_probe_hello.ogg b/backend/app/assets/health_probe_hello.ogg new file mode 100644 index 0000000000000000000000000000000000000000..933c0ef6fa0679ce2b7602dbbcee075842820bf9 GIT binary patch literal 15322 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 dict: - from sqlmodel import Session - - from app.core.db import engine - from app.services.health_probes import run_probes + from app.services.health_probes import execute_health_probes _set_trace(trace_id) - - def _do() -> dict: - with Session(engine) as session: - return run_probes(session=session) - - return _run_with_otel_parent(self, _do) + return _run_with_otel_parent(self, execute_health_probes) @celery_app.task(bind=True, queue="default", priority=1) diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index 56d5b9ad7..17f0b25d0 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -1,15 +1,19 @@ -import base64 import logging import time from concurrent.futures import ThreadPoolExecutor from dataclasses import dataclass +from pathlib import Path from typing import Any, Literal +from sentry_sdk.crons import MonitorStatus, capture_checkin +from sentry_sdk.types import MonitorConfig from sqlmodel import Session from app.core.audio_utils import AudioRef from app.core.config import settings -from app.models.llm import KaapiCompletionConfig, QueryParams +from app.core.db import engine +from app.models.llm import KaapiCompletionConfig, NativeCompletionConfig, QueryParams +from app.services.llm.mappers import transform_kaapi_config_to_native from app.services.llm.providers.base import BaseProvider from app.services.llm.providers.registry import get_llm_provider @@ -19,9 +23,26 @@ _PROBE_MAX_TOKENS = 1 _PROBE_WORKERS = 4 -# "Hello" ~1sec -_STT_AUDIO_B64: str = "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" -_STT_AUDIO_MIME: str = "audio/ogg" +# ~1sec "Hello" clip used as STT probe input. +_STT_AUDIO_PATH = ( + Path(__file__).resolve().parents[1] / "assets" / "health_probe_hello.ogg" +) +_STT_AUDIO_MIME = "audio/ogg" +_stt_audio_bytes: bytes | None = None + +HEALTH_PROBES_MONITOR_SLUG = "health-probes-cron-job" +HEALTH_PROBES_MONITOR_CONFIG: MonitorConfig = { + "schedule": { + "type": "interval", + "value": settings.HEALTH_PROBE_INTERVAL_MINUTES, + "unit": "minute", + }, + "timezone": "UTC", + "checkin_margin": 2, + "max_runtime": 2 * settings.HEALTH_PROBE_INTERVAL_MINUTES, + "failure_issue_threshold": 2, + "recovery_threshold": 1, +} Modality = Literal["text", "tts", "stt"] @@ -34,14 +55,21 @@ class Probe: modality: Modality +# (probe, provider, built config+input, build error) — exactly one of the last +# two is set; a build error short-circuits _run_probe before provider.execute. +BuiltProbe = tuple[NativeCompletionConfig, str | AudioRef] +PreparedProbe = tuple[Probe, BaseProvider | None, BuiltProbe | None, str | None] + + _PROBES: list[Probe] = [ # Text Probe(provider="openai", model="gpt-4o-mini", modality="text"), Probe(provider="google", model="gemini-2.5-flash", modality="text"), Probe(provider="google", model="gemini-2.5-pro", modality="text"), + Probe(provider="anthropic", model="claude-sonnet-4-6", modality="text"), # TTS Probe(provider="google", model="gemini-2.5-flash-preview-tts", modality="tts"), - Probe(provider="google", model="gemini-3.1-flash-preview-tts", modality="tts"), + Probe(provider="google", model="gemini-3.1-flash-tts-preview", modality="tts"), Probe(provider="google", model="gemini-2.5-pro-preview-tts", modality="tts"), Probe(provider="sarvamai", model="bulbul:v3", modality="tts"), Probe(provider="elevenlabs", model="eleven_v3", modality="tts"), @@ -54,6 +82,21 @@ class Probe: ] +def _load_stt_audio() -> bytes | None: + global _stt_audio_bytes + if _stt_audio_bytes is None: + try: + with open(_STT_AUDIO_PATH, "rb") as f: + _stt_audio_bytes = f.read() + except OSError as e: + logger.warning( + f"[_load_stt_audio] Probe audio unavailable | " + f"path: {_STT_AUDIO_PATH}, error: {e}" + ) + return None + return _stt_audio_bytes + + def _build_provider( session: Session, probe: Probe, *, org_id: int, project_id: int ) -> BaseProvider | None: @@ -72,9 +115,7 @@ def _build_provider( return None -def _build_config_and_input( - probe: Probe, -) -> tuple[KaapiCompletionConfig, str | AudioRef] | None: +def _build_config_and_input(session: Session, probe: Probe) -> BuiltProbe | None: if probe.modality == "text": cfg = KaapiCompletionConfig.model_validate( { @@ -87,9 +128,8 @@ def _build_config_and_input( }, } ) - return cfg, _PROBE_INPUT - - if probe.modality == "tts": + resolved_input: str | AudioRef = _PROBE_INPUT + elif probe.modality == "tts": cfg = KaapiCompletionConfig.model_validate( { "provider": probe.provider, @@ -97,26 +137,32 @@ def _build_config_and_input( "params": {"model": probe.model}, } ) - return cfg, _PROBE_INPUT + resolved_input = _PROBE_INPUT + else: # stt + audio_bytes = _load_stt_audio() + if audio_bytes is None: + return None + cfg = KaapiCompletionConfig.model_validate( + { + "provider": probe.provider, + "type": "stt", + "params": {"model": probe.model}, + } + ) + resolved_input = AudioRef(bytes_=audio_bytes, mime_type=_STT_AUDIO_MIME) - # stt - if not _STT_AUDIO_B64: - return None - cfg = KaapiCompletionConfig.model_validate( - { - "provider": probe.provider, - "type": "stt", - "params": {"model": probe.model}, - } + native_config, _ = transform_kaapi_config_to_native( + session=session, kaapi_config=cfg ) - audio = AudioRef( - bytes_=base64.b64decode(_STT_AUDIO_B64), - mime_type=_STT_AUDIO_MIME, - ) - return cfg, audio + return native_config, resolved_input -def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: +def _run_probe( + probe: Probe, + provider: BaseProvider | None, + built: BuiltProbe | None, + build_error: str | None, +) -> dict[str, Any]: result: dict[str, Any] = { "endpoint": "llm/call", "provider": probe.provider, @@ -126,29 +172,17 @@ def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: "latency_ms": None, "error": None, } - if provider is None: - result["error"] = "client_init_failed" + if build_error is not None or provider is None or built is None: + result["error"] = build_error or "not_prepared" return result - try: - built = _build_config_and_input(probe) - except Exception as e: - result["error"] = f"{type(e).__name__}: {e}" - logger.error( - f"[_run_probe] Config build failed | provider: {probe.provider}, " - f"modality: {probe.modality}, error: {result['error']}" - ) - return result - if built is None: - result["error"] = "stt_audio_not_configured" - return result config, resolved_input = built query = QueryParams(input=_PROBE_INPUT if isinstance(resolved_input, str) else "") started = time.perf_counter() try: response, error = provider.execute( - completion_config=config, # type: ignore[arg-type] + completion_config=config, query=query, resolved_input=resolved_input, ) @@ -174,7 +208,40 @@ def _run_probe(provider: BaseProvider | None, probe: Probe) -> dict[str, Any]: return result -def run_probes(*, session: Session) -> dict[str, Any]: +def _prepare_probes( + session: Session, *, org_id: int, project_id: int +) -> list[PreparedProbe]: + provider_cache: dict[str, BaseProvider | None] = {} + for p in _PROBES: + if p.provider not in provider_cache: + provider_cache[p.provider] = _build_provider( + session, p, org_id=org_id, project_id=project_id + ) + + prepared: list[PreparedProbe] = [] + for p in _PROBES: + provider = provider_cache[p.provider] + if provider is None: + prepared.append((p, None, None, "client_init_failed")) + continue + try: + built = _build_config_and_input(session, p) + except Exception as e: + error = f"{type(e).__name__}: {e}" + logger.error( + f"[_prepare_probes] Config build failed | provider: {p.provider}, " + f"modality: {p.modality}, error: {error}" + ) + prepared.append((p, provider, None, error)) + continue + if built is None: + prepared.append((p, provider, None, "stt_audio_not_configured")) + continue + prepared.append((p, provider, built, None)) + return prepared + + +def run_probes() -> dict[str, Any]: org_id = settings.HEALTH_PROBE_ORG_ID project_id = settings.HEALTH_PROBE_PROJECT_ID if org_id is None or project_id is None: @@ -188,17 +255,14 @@ def run_probes(*, session: Session) -> dict[str, Any]: f"org_id: {org_id}, project_id: {project_id}" ) - provider_cache: dict[str, BaseProvider | None] = {} - for p in _PROBES: - if p.provider not in provider_cache: - provider_cache[p.provider] = _build_provider( - session, p, org_id=org_id, project_id=project_id - ) - dispatch = [(p, provider_cache[p.provider]) for p in _PROBES] + # Session covers only preparation (credential lookup + config transform); + # it must be closed before the slow external provider calls below. + with Session(engine) as session: + prepared = _prepare_probes(session, org_id=org_id, project_id=project_id) started = time.perf_counter() with ThreadPoolExecutor(max_workers=_PROBE_WORKERS) as pool: - results = list(pool.map(lambda pp: _run_probe(pp[1], pp[0]), dispatch)) + results = list(pool.map(lambda pp: _run_probe(*pp), prepared)) elapsed_ms = int((time.perf_counter() - started) * 1000) ok_count = sum(1 for r in results if r["ok"]) @@ -213,3 +277,49 @@ def run_probes(*, session: Session) -> dict[str, Any]: "failed": len(results) - ok_count, "results": results, } + + +def execute_health_probes() -> dict[str, Any]: + """Run the probes wrapped in Sentry cron check-ins. + + The check-in happens here (not in the cron route) so the monitor reflects + actual probe results rather than enqueue success. + """ + check_in_id = capture_checkin( + monitor_slug=HEALTH_PROBES_MONITOR_SLUG, + status=MonitorStatus.IN_PROGRESS, + monitor_config=HEALTH_PROBES_MONITOR_CONFIG, + ) + try: + result = run_probes() + except Exception: + capture_checkin( + check_in_id=check_in_id, + monitor_slug=HEALTH_PROBES_MONITOR_SLUG, + status=MonitorStatus.ERROR, + ) + raise + + ok = not result.get("skipped") and result.get("failed") == 0 + capture_checkin( + check_in_id=check_in_id, + monitor_slug=HEALTH_PROBES_MONITOR_SLUG, + status=MonitorStatus.OK if ok else MonitorStatus.ERROR, + ) + return result + + +def main() -> None: + """Manual smoke test: `uv run python -m app.services.health_probes`. + + Calls run_probes directly (no Sentry check-ins) against the configured + HEALTH_PROBE_ORG_ID/PROJECT_ID — real provider calls, real credentials. + """ + import json + + logging.basicConfig(level=logging.INFO) + print(json.dumps(run_probes(), indent=2)) + + +if __name__ == "__main__": + main() diff --git a/backend/app/tests/celery/test_run_health_probes.py b/backend/app/tests/celery/test_run_health_probes.py index b7ebde3f1..64a30e2ee 100644 --- a/backend/app/tests/celery/test_run_health_probes.py +++ b/backend/app/tests/celery/test_run_health_probes.py @@ -1,86 +1,24 @@ +from typing import Any from unittest.mock import patch -from sqlmodel import Session - from app.celery.tasks import job_execution -class _NonClosingSession: - def __init__(self, session: Session): - self._session = session - - def __enter__(self) -> Session: - return self._session - - def __exit__(self, exc_type, exc, tb) -> bool: - return False - - -def test_run_health_probes_task_returns_run_probes_result(db: Session): - canned = { +def test_run_health_probes_task_returns_execute_result() -> None: + canned: dict[str, Any] = { "elapsed_ms": 42, "total": 3, "ok": 3, "failed": 0, - "results": [ - { - "endpoint": "llm/call", - "provider": "openai", - "modality": "text", - "model": "gpt-4o-1-mini", - "ok": True, - "latency_ms": 10, - "error": None, - } - ], + "results": [], } - captured: dict = {} - - def _fake_run_probes(*, session: Session) -> dict: - captured["session"] = session - return canned - - with ( - patch( - "app.services.health_probes.run_probes", - side_effect=_fake_run_probes, - ), - patch( - "app.core.db.engine", - new=object(), # engine is only fed to Session() which we intercept below - ), - patch( - "sqlmodel.Session", - side_effect=lambda _engine: _NonClosingSession(db), - ), - ): + # the task lazy-imports execute_health_probes, so patch it at its source module + with patch( + "app.services.health_probes.execute_health_probes", + return_value=canned, + ) as execute_mock: result = job_execution.run_health_probes.apply(args=[]).get() assert result == canned - assert captured["session"] is db - - -def test_run_health_probes_task_skipped_when_settings_unset(db: Session): - skipped = { - "skipped": True, - "reason": "health_probe_org_or_project_not_set", - } - - with ( - patch( - "app.services.health_probes.run_probes", - return_value=skipped, - ), - patch( - "app.core.db.engine", - new=object(), - ), - patch( - "sqlmodel.Session", - side_effect=lambda _engine: _NonClosingSession(db), - ), - ): - result = job_execution.run_health_probes.apply(args=[]).get() - - assert result == skipped + execute_mock.assert_called_once_with() diff --git a/backend/app/tests/services/test_health_probes.py b/backend/app/tests/services/test_health_probes.py index d2a2e85a8..96efc7276 100644 --- a/backend/app/tests/services/test_health_probes.py +++ b/backend/app/tests/services/test_health_probes.py @@ -1,19 +1,61 @@ +from pathlib import Path +from types import TracebackType +from typing import Any + import pytest from sqlmodel import Session +from app.core.audio_utils import AudioRef from app.core.config import settings +from app.models.llm import NativeCompletionConfig, QueryParams from app.services import health_probes -from app.services.health_probes import _PROBES, run_probes +from app.services.health_probes import ( + HEALTH_PROBES_MONITOR_CONFIG, + HEALTH_PROBES_MONITOR_SLUG, + _PROBES, + execute_health_probes, + run_probes, +) + + +class _NonClosingSession: + """Stands in for `Session(engine)` inside run_probes, yielding the + conftest transactional session without closing it on __exit__.""" + + def __init__(self, session: Session): + self._session = session + + def __enter__(self) -> Session: + return self._session + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + tb: TracebackType | None, + ) -> bool: + return False class _FakeProvider: - def __init__(self, response=None, error=None, raise_exc: Exception | None = None): + def __init__( + self, + response: Any = None, + error: str | None = None, + raise_exc: Exception | None = None, + ): self._response = response self._error = error self._raise_exc = raise_exc - self.calls: list[dict] = [] - - def execute(self, *, completion_config, query, resolved_input): + self.calls: list[dict[str, Any]] = [] + + def execute( + self, + *, + completion_config: NativeCompletionConfig, + query: QueryParams, + resolved_input: str | AudioRef, + ) -> tuple[Any, str | None]: self.calls.append( { "completion_config": completion_config, @@ -27,33 +69,38 @@ def execute(self, *, completion_config, query, resolved_input): @pytest.fixture -def configured_probe_settings(monkeypatch): +def configured_probe_settings(db: Session, monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", 1) monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", 1) + # run_probes opens its own Session(engine); point it at the conftest + # transactional session so nothing leaks past the test. + monkeypatch.setattr( + health_probes, "Session", lambda _engine: _NonClosingSession(db) + ) class TestSkipWhenNotConfigured: - def test_returns_skipped_when_org_id_missing(self, db: Session, monkeypatch): + def test_returns_skipped_when_org_id_missing( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", None) monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", 1) + monkeypatch.setattr( + health_probes, + "Session", + lambda _engine: pytest.fail("no session must be opened when skipping"), + ) - called = {"n": 0} - - def _tracker(**_kwargs): - called["n"] += 1 - return _FakeProvider(response={"ok": True}) - - monkeypatch.setattr(health_probes, "get_llm_provider", _tracker) - - result = run_probes(session=db) + result = run_probes() assert result == { "skipped": True, "reason": "health_probe_org_or_project_not_set", } - assert called["n"] == 0 - def test_returns_skipped_when_project_id_missing(self, db: Session, monkeypatch): + def test_returns_skipped_when_project_id_missing( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", 1) monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", None) monkeypatch.setattr( @@ -62,7 +109,7 @@ def test_returns_skipped_when_project_id_missing(self, db: Session, monkeypatch) lambda **_k: pytest.fail("provider must not be built"), ) - result = run_probes(session=db) + result = run_probes() assert result["skipped"] is True assert result["reason"] == "health_probe_org_or_project_not_set" @@ -70,12 +117,12 @@ def test_returns_skipped_when_project_id_missing(self, db: Session, monkeypatch) class TestRunProbesShape: def test_all_probes_ok_returns_expected_structure( - self, db: Session, monkeypatch, configured_probe_settings - ): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: fake = _FakeProvider(response={"data": "pong"}, error=None) monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - result = run_probes(session=db) + result = run_probes() assert set(result.keys()) == { "elapsed_ms", @@ -105,17 +152,23 @@ def test_all_probes_ok_returns_expected_structure( assert r["error"] is None assert isinstance(r["latency_ms"], int) + # the config build must hand the provider a native config, not the Kaapi one + assert all( + isinstance(c["completion_config"], NativeCompletionConfig) + for c in fake.calls + ) + class TestProviderInitFailure: def test_get_llm_provider_value_error_marks_client_init_failed( - self, db: Session, monkeypatch, configured_probe_settings - ): - def _boom(**_kwargs): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: + def _boom(**_kwargs: Any) -> _FakeProvider: raise ValueError("no creds") monkeypatch.setattr(health_probes, "get_llm_provider", _boom) - result = run_probes(session=db) + result = run_probes() assert result["ok"] == 0 assert result["failed"] == len(_PROBES) @@ -125,15 +178,15 @@ def _boom(**_kwargs): assert r["latency_ms"] is None def test_get_llm_provider_runtime_error_marks_client_init_failed( - self, db: Session, monkeypatch, configured_probe_settings - ): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: monkeypatch.setattr( health_probes, "get_llm_provider", lambda **_k: (_ for _ in ()).throw(RuntimeError("bad")), ) - result = run_probes(session=db) + result = run_probes() assert result["failed"] == len(_PROBES) assert all(r["error"] == "client_init_failed" for r in result["results"]) @@ -142,12 +195,12 @@ def test_get_llm_provider_runtime_error_marks_client_init_failed( class TestExecuteBehaviors: def test_execute_raises_marks_error_with_exception_class_name( - self, db: Session, monkeypatch, configured_probe_settings - ): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: fake = _FakeProvider(raise_exc=TimeoutError("slow")) monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - result = run_probes(session=db) + result = run_probes() assert result["ok"] == 0 for r in result["results"]: @@ -157,12 +210,12 @@ def test_execute_raises_marks_error_with_exception_class_name( assert isinstance(r["latency_ms"], int) def test_provider_returns_none_response_uses_provided_error( - self, db: Session, monkeypatch, configured_probe_settings - ): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: fake = _FakeProvider(response=None, error="some_error") monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - result = run_probes(session=db) + result = run_probes() assert result["ok"] == 0 assert result["failed"] == len(_PROBES) @@ -172,24 +225,24 @@ def test_provider_returns_none_response_uses_provided_error( assert isinstance(r["latency_ms"], int) def test_provider_returns_none_response_and_no_error_defaults_no_response( - self, db: Session, monkeypatch, configured_probe_settings - ): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: fake = _FakeProvider(response=None, error=None) monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - result = run_probes(session=db) + result = run_probes() for r in result["results"]: assert r["ok"] is False assert r["error"] == "no_response" def test_provider_returns_response_marks_ok( - self, db: Session, monkeypatch, configured_probe_settings - ): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: fake = _FakeProvider(response={"ok": 1}, error=None) monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - result = run_probes(session=db) + result = run_probes() assert result["ok"] == len(_PROBES) for r in result["results"]: @@ -198,14 +251,18 @@ def test_provider_returns_response_marks_ok( class TestSttAudioNotConfigured: - def test_empty_stt_audio_short_circuits_stt_probes( - self, db: Session, monkeypatch, configured_probe_settings - ): - monkeypatch.setattr(health_probes, "_STT_AUDIO_B64", "") + def test_missing_stt_audio_file_short_circuits_stt_probes( + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: + monkeypatch.setattr( + health_probes, "_STT_AUDIO_PATH", Path("/nonexistent/probe.ogg") + ) + # reset the lazy-load cache so the missing path is actually read + monkeypatch.setattr(health_probes, "_stt_audio_bytes", None) fake = _FakeProvider(response={"ok": 1}, error=None) monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - result = run_probes(session=db) + result = run_probes() stt_results = [r for r in result["results"] if r["modality"] == "stt"] assert stt_results, "expected at least one STT probe" @@ -222,19 +279,102 @@ def test_empty_stt_audio_short_circuits_stt_probes( class TestProviderCaching: def test_get_llm_provider_called_once_per_unique_provider( - self, db: Session, monkeypatch, configured_probe_settings - ): + self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + ) -> None: seen_providers: list[str] = [] - def _factory(**kwargs): + def _factory(**kwargs: Any) -> _FakeProvider: seen_providers.append(kwargs["provider_type"]) return _FakeProvider(response={"ok": 1}, error=None) monkeypatch.setattr(health_probes, "get_llm_provider", _factory) - run_probes(session=db) + run_probes() unique_probe_providers = {p.provider for p in _PROBES} # One factory call per unique provider name, not per probe assert sorted(seen_providers) == sorted(unique_probe_providers) assert len(seen_providers) < len(_PROBES) + + +class TestExecuteHealthProbes: + @staticmethod + def _patch_checkin( + monkeypatch: pytest.MonkeyPatch, + ) -> list[dict[str, Any]]: + checkins: list[dict[str, Any]] = [] + + def _capture(**kwargs: Any) -> str: + checkins.append(kwargs) + return "checkin-123" + + monkeypatch.setattr(health_probes, "capture_checkin", _capture) + return checkins + + def test_ok_result_closes_checkin_with_ok( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: + checkins = self._patch_checkin(monkeypatch) + canned = {"elapsed_ms": 1, "total": 2, "ok": 2, "failed": 0, "results": []} + monkeypatch.setattr(health_probes, "run_probes", lambda: canned) + + result = execute_health_probes() + + assert result == canned + assert len(checkins) == 2 + assert checkins[0] == { + "monitor_slug": HEALTH_PROBES_MONITOR_SLUG, + "status": health_probes.MonitorStatus.IN_PROGRESS, + "monitor_config": HEALTH_PROBES_MONITOR_CONFIG, + } + assert checkins[1] == { + "check_in_id": "checkin-123", + "monitor_slug": HEALTH_PROBES_MONITOR_SLUG, + "status": health_probes.MonitorStatus.OK, + } + + def test_failed_probes_close_checkin_with_error( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: + checkins = self._patch_checkin(monkeypatch) + canned = {"elapsed_ms": 1, "total": 2, "ok": 1, "failed": 1, "results": []} + monkeypatch.setattr(health_probes, "run_probes", lambda: canned) + + result = execute_health_probes() + + assert result == canned + assert checkins[1]["status"] == health_probes.MonitorStatus.ERROR + assert checkins[1]["check_in_id"] == "checkin-123" + + def test_skipped_result_closes_checkin_with_error( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: + checkins = self._patch_checkin(monkeypatch) + skipped = {"skipped": True, "reason": "health_probe_org_or_project_not_set"} + monkeypatch.setattr(health_probes, "run_probes", lambda: skipped) + + result = execute_health_probes() + + assert result == skipped + assert checkins[1]["status"] == health_probes.MonitorStatus.ERROR + + def test_run_probes_raising_sends_error_checkin_and_propagates( + self, monkeypatch: pytest.MonkeyPatch + ) -> None: + checkins = self._patch_checkin(monkeypatch) + + def _boom() -> dict[str, Any]: + raise RuntimeError("probe explosion") + + monkeypatch.setattr(health_probes, "run_probes", _boom) + + with pytest.raises(RuntimeError, match="probe explosion"): + execute_health_probes() + + assert len(checkins) == 2 + assert checkins[0]["status"] == health_probes.MonitorStatus.IN_PROGRESS + assert checkins[1] == { + "check_in_id": "checkin-123", + "monitor_slug": HEALTH_PROBES_MONITOR_SLUG, + "status": health_probes.MonitorStatus.ERROR, + } From b8c6aa0ba15ed5982bc953b293dc46653c67a137 Mon Sep 17 00:00:00 2001 From: Prajna1999 Date: Thu, 30 Jul 2026 21:44:07 +0530 Subject: [PATCH 10/11] redis hook up with round robin probe check --- backend/app/api/routes/cron.py | 19 +- backend/app/celery/tasks/job_execution.py | 9 - backend/app/core/config.py | 2 +- backend/app/services/health_probes.py | 393 ++++++-------- .../api/routes/test_cron_health_probes.py | 47 +- .../tests/celery/test_run_health_probes.py | 24 - .../app/tests/services/test_health_probes.py | 498 ++++++------------ docs/wiki/INDEX.md | 2 +- docs/wiki/modules/platform.md | 2 +- features/health-probes/SRD.md | 110 ++++ features/health-probes/assets/flow-a.mmd | 27 + features/health-probes/assets/flow-a.png | Bin 0 -> 313795 bytes 12 files changed, 520 insertions(+), 613 deletions(-) delete mode 100644 backend/app/tests/celery/test_run_health_probes.py create mode 100644 features/health-probes/SRD.md create mode 100644 features/health-probes/assets/flow-a.mmd create mode 100644 features/health-probes/assets/flow-a.png diff --git a/backend/app/api/routes/cron.py b/backend/app/api/routes/cron.py index 80c15f827..9a95b721b 100644 --- a/backend/app/api/routes/cron.py +++ b/backend/app/api/routes/cron.py @@ -1,4 +1,5 @@ import logging +from typing import Any import sentry_sdk from fastapi import APIRouter, Depends @@ -7,8 +8,8 @@ from app.api.deps import SessionDep from app.api.permissions import Permission, require_permission from app.core.config import settings -from app.celery.tasks.job_execution import run_health_probes from app.crud.evaluations import process_all_pending_evaluations +from app.services.health_probes import run_health_probe_tick from app.services.job_monitoring import monitor_pending_jobs logger = logging.getLogger(__name__) @@ -127,12 +128,16 @@ async def evaluation_cron_job( include_in_schema=False, dependencies=[Depends(require_permission(Permission.SUPERUSER))], ) -def health_probes_cron_job() -> dict: - # Sentry check-ins happen inside the Celery task so the monitor reflects - # probe results, not just enqueue success. - logger.info("[health_probes_cron_job] Cron job invoked — enqueueing task") - async_result = run_health_probes.delay() - return {"enqueued": True, "task_id": async_result.id} +def health_probes_cron_job() -> dict[str, Any]: + # Runs synchronously (no Celery task of its own) — the probe rides the + # existing LLM_API job pipeline via `start_job`. + logger.info("[health_probes_cron_job] Cron job invoked") + result = run_health_probe_tick() + logger.info( + f"[health_probes_cron_job] Tick complete | job_id: {result.get('job_id')}, " + f"probe_index: {result.get('probe_index')}" + ) + return result @router.get( diff --git a/backend/app/celery/tasks/job_execution.py b/backend/app/celery/tasks/job_execution.py index 4d9c0cc5b..fcf7b1cfe 100644 --- a/backend/app/celery/tasks/job_execution.py +++ b/backend/app/celery/tasks/job_execution.py @@ -424,15 +424,6 @@ def run_evaluation_fast_aggregate( ) -@celery_app.task(bind=True, queue="default", priority=2) -@gevent_timeout(settings.CELERY_TASK_SOFT_TIME_LIMIT, "run_health_probes") -def run_health_probes(self, trace_id: str = DEFAULT_TRACE_ID) -> dict: - from app.services.health_probes import execute_health_probes - - _set_trace(trace_id) - return _run_with_otel_parent(self, execute_health_probes) - - @celery_app.task(bind=True, queue="default", priority=1) @gevent_timeout( settings.CELERY_TASK_SOFT_TIME_LIMIT, "send_eval_completion_notification" diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 3c911749e..c06f36805 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -195,7 +195,7 @@ def AWS_S3_BUCKET(self) -> str: HEALTH_PROBE_ORG_ID: int | None = None HEALTH_PROBE_PROJECT_ID: int | None = None - HEALTH_PROBE_INTERVAL_MINUTES: int = 5 + HEALTH_PROBE_INTERVAL_MINUTES: int = 3 # AI-assisted prompt improvement settings. # See docs/srd-ai-prompt-improvement.md for the full design rationale. diff --git a/backend/app/services/health_probes.py b/backend/app/services/health_probes.py index 17f0b25d0..be6b4a7f8 100644 --- a/backend/app/services/health_probes.py +++ b/backend/app/services/health_probes.py @@ -1,34 +1,41 @@ +import base64 import logging -import time -from concurrent.futures import ThreadPoolExecutor -from dataclasses import dataclass +from dataclasses import dataclass, field from pathlib import Path from typing import Any, Literal +from uuid import UUID +import redis from sentry_sdk.crons import MonitorStatus, capture_checkin from sentry_sdk.types import MonitorConfig from sqlmodel import Session -from app.core.audio_utils import AudioRef from app.core.config import settings from app.core.db import engine -from app.models.llm import KaapiCompletionConfig, NativeCompletionConfig, QueryParams -from app.services.llm.mappers import transform_kaapi_config_to_native -from app.services.llm.providers.base import BaseProvider -from app.services.llm.providers.registry import get_llm_provider +from app.crud.jobs import JobCrud +from app.models.job import JobStatus +from app.models.llm.constants import CompletionType +from app.models.llm.request import ( + AudioContent, + AudioInput, + ConfigBlob, + KaapiCompletionConfig, + LLMCallConfig, + LLMCallRequest, + QueryParams, +) +from app.services.llm.jobs import start_job logger = logging.getLogger(__name__) _PROBE_INPUT = "ping" -_PROBE_MAX_TOKENS = 1 -_PROBE_WORKERS = 4 -# ~1sec "Hello" clip used as STT probe input. +# ~1sec "Hello" clip used as the STT probe's input audio. _STT_AUDIO_PATH = ( Path(__file__).resolve().parents[1] / "assets" / "health_probe_hello.ogg" ) _STT_AUDIO_MIME = "audio/ogg" -_stt_audio_bytes: bytes | None = None +_stt_audio_b64: str | None = None HEALTH_PROBES_MONITOR_SLUG = "health-probes-cron-job" HEALTH_PROBES_MONITOR_CONFIG: MonitorConfig = { @@ -44,6 +51,11 @@ "recovery_threshold": 1, } +# Rotation state lives in Redis, not a table — no CRUD, no tenant isolation needed. +_LAST_JOB_ID_KEY = "health_probe:last_job_id" +_INDEX_KEY = "health_probe:index" + +_redis_client: redis.Redis = redis.from_url(settings.REDIS_URL, decode_responses=True) Modality = Literal["text", "tts", "stt"] @@ -53,12 +65,9 @@ class Probe: provider: str model: str modality: Modality - - -# (probe, provider, built config+input, build error) — exactly one of the last -# two is set; a build error short-circuits _run_probe before provider.execute. -BuiltProbe = tuple[NativeCompletionConfig, str | AudioRef] -PreparedProbe = tuple[Probe, BaseProvider | None, BuiltProbe | None, str | None] + # Extra Kaapi params a provider's mapper requires beyond `model` + # (Sarvam TTS needs `language`, ElevenLabs TTS needs `voice`). + params: dict[str, Any] = field(default_factory=dict) _PROBES: list[Probe] = [ @@ -71,8 +80,18 @@ class Probe: Probe(provider="google", model="gemini-2.5-flash-preview-tts", modality="tts"), Probe(provider="google", model="gemini-3.1-flash-tts-preview", modality="tts"), Probe(provider="google", model="gemini-2.5-pro-preview-tts", modality="tts"), - Probe(provider="sarvamai", model="bulbul:v3", modality="tts"), - Probe(provider="elevenlabs", model="eleven_v3", modality="tts"), + Probe( + provider="sarvamai", + model="bulbul:v3", + modality="tts", + params={"language": "en-IN"}, + ), + Probe( + provider="elevenlabs", + model="eleven_v3", + modality="tts", + params={"voice": "Sarah"}, + ), # STT Probe(provider="google", model="gemini-2.5-pro", modality="stt"), Probe(provider="google", model="gemini-2.5-flash", modality="stt"), @@ -82,244 +101,162 @@ class Probe: ] -def _load_stt_audio() -> bytes | None: - global _stt_audio_bytes - if _stt_audio_bytes is None: - try: - with open(_STT_AUDIO_PATH, "rb") as f: - _stt_audio_bytes = f.read() - except OSError as e: - logger.warning( - f"[_load_stt_audio] Probe audio unavailable | " - f"path: {_STT_AUDIO_PATH}, error: {e}" +def _load_stt_audio_b64() -> str: + global _stt_audio_b64 + if _stt_audio_b64 is None: + with open(_STT_AUDIO_PATH, "rb") as f: + _stt_audio_b64 = base64.b64encode(f.read()).decode("ascii") + return _stt_audio_b64 + + +def _build_probe_request(probe: Probe, index: int) -> LLMCallRequest: + completion_type = { + "text": CompletionType.TEXT, + "tts": CompletionType.TTS, + "stt": CompletionType.STT, + }[probe.modality] + + kaapi_config = KaapiCompletionConfig( + provider=probe.provider, + type=completion_type, + params={"model": probe.model, **probe.params}, + ) + + if probe.modality == "stt": + query_input: str | AudioInput = AudioInput( + content=AudioContent( + format="base64", + value=_load_stt_audio_b64(), + mime_type=_STT_AUDIO_MIME, ) - return None - return _stt_audio_bytes + ) + else: + query_input = _PROBE_INPUT + + # No callback_url: the probe reads its result by polling `Job.status` on + # the next tick, so callback delivery (a best-effort side channel that + # never affects Job.status) buys nothing here. + return LLMCallRequest( + query=QueryParams(input=query_input), + config=LLMCallConfig(blob=ConfigBlob(completion=kaapi_config)), + request_metadata={ + "health_probe": True, + "probe_index": index, + "provider": probe.provider, + "modality": probe.modality, + "model": probe.model, + }, + ) -def _build_provider( - session: Session, probe: Probe, *, org_id: int, project_id: int -) -> BaseProvider | None: +def _check_previous_probe(project_id: int) -> JobStatus | None: + # Missing key (first run, Redis eviction) means skip the check-in, not fail the tick. try: - return get_llm_provider( - session=session, - provider_type=probe.provider, - project_id=project_id, - organization_id=org_id, - ) - except (ValueError, RuntimeError) as e: + last_job_id = _redis_client.get(_LAST_JOB_ID_KEY) + except redis.RedisError as e: + logger.warning(f"[_check_previous_probe] Redis GET failed | error: {e}") + return None + + if last_job_id is None: logger.warning( - f"[_build_provider] Client init failed | provider: {probe.provider}, " - f"modality: {probe.modality}, error: {e}" + f"[_check_previous_probe] {_LAST_JOB_ID_KEY} missing — skipping check-in" ) return None - -def _build_config_and_input(session: Session, probe: Probe) -> BuiltProbe | None: - if probe.modality == "text": - cfg = KaapiCompletionConfig.model_validate( - { - "provider": probe.provider, - "type": "text", - "params": { - "model": probe.model, - "temperature": 0.0, - "max_output_tokens": _PROBE_MAX_TOKENS, - }, - } - ) - resolved_input: str | AudioRef = _PROBE_INPUT - elif probe.modality == "tts": - cfg = KaapiCompletionConfig.model_validate( - { - "provider": probe.provider, - "type": "tts", - "params": {"model": probe.model}, - } - ) - resolved_input = _PROBE_INPUT - else: # stt - audio_bytes = _load_stt_audio() - if audio_bytes is None: - return None - cfg = KaapiCompletionConfig.model_validate( - { - "provider": probe.provider, - "type": "stt", - "params": {"model": probe.model}, - } + with Session(engine) as session: + job = JobCrud(session=session).get( + job_id=UUID(str(last_job_id)), project_id=project_id ) - resolved_input = AudioRef(bytes_=audio_bytes, mime_type=_STT_AUDIO_MIME) - native_config, _ = transform_kaapi_config_to_native( - session=session, kaapi_config=cfg - ) - return native_config, resolved_input - - -def _run_probe( - probe: Probe, - provider: BaseProvider | None, - built: BuiltProbe | None, - build_error: str | None, -) -> dict[str, Any]: - result: dict[str, Any] = { - "endpoint": "llm/call", - "provider": probe.provider, - "modality": probe.modality, - "model": probe.model, - "ok": False, - "latency_ms": None, - "error": None, - } - if build_error is not None or provider is None or built is None: - result["error"] = build_error or "not_prepared" - return result + if job is None: + logger.warning(f"[_check_previous_probe] Job not found | job_id: {last_job_id}") + return None - config, resolved_input = built - query = QueryParams(input=_PROBE_INPUT if isinstance(resolved_input, str) else "") + return job.status - started = time.perf_counter() - try: - response, error = provider.execute( - completion_config=config, - query=query, - resolved_input=resolved_input, - ) - except Exception as e: - result["latency_ms"] = int((time.perf_counter() - started) * 1000) - result["error"] = f"{type(e).__name__}: {e}" - logger.error( - f"[_run_probe] Raised | provider: {probe.provider}, " - f"modality: {probe.modality}, error: {result['error']}" - ) - return result - result["latency_ms"] = int((time.perf_counter() - started) * 1000) - if response is None: - result["error"] = error or "no_response" - logger.error( - f"[_run_probe] Failed | provider: {probe.provider}, " - f"modality: {probe.modality}, error: {result['error']}" - ) - return result +def _capture_previous_result_checkin(previous_status: JobStatus | None) -> None: + if previous_status is None: + return + # SUCCESS means the probe actually ran and returned; FAILED or a + # still-PENDING/PROCESSING job both mean a real failure. + monitor_status = ( + MonitorStatus.OK + if previous_status == JobStatus.SUCCESS + else MonitorStatus.ERROR + ) + capture_checkin( + monitor_slug=HEALTH_PROBES_MONITOR_SLUG, + status=monitor_status, + monitor_config=HEALTH_PROBES_MONITOR_CONFIG, + ) - result["ok"] = True - return result +def _claim_next_probe_index() -> int: + # Redis INCR is atomic, so two overlapping ticks can never claim the same + # slot (which would fire the same probe twice while skipping another). + try: + count = _redis_client.incr(_INDEX_KEY) + except redis.RedisError as e: + logger.warning(f"[_claim_next_probe_index] Redis INCR failed | error: {e}") + return 0 -def _prepare_probes( - session: Session, *, org_id: int, project_id: int -) -> list[PreparedProbe]: - provider_cache: dict[str, BaseProvider | None] = {} - for p in _PROBES: - if p.provider not in provider_cache: - provider_cache[p.provider] = _build_provider( - session, p, org_id=org_id, project_id=project_id - ) + try: + return (int(count) - 1) % len(_PROBES) + except (TypeError, ValueError): + logger.warning(f"[_claim_next_probe_index] Non-integer index | raw: {count!r}") + return 0 - prepared: list[PreparedProbe] = [] - for p in _PROBES: - provider = provider_cache[p.provider] - if provider is None: - prepared.append((p, None, None, "client_init_failed")) - continue - try: - built = _build_config_and_input(session, p) - except Exception as e: - error = f"{type(e).__name__}: {e}" - logger.error( - f"[_prepare_probes] Config build failed | provider: {p.provider}, " - f"modality: {p.modality}, error: {error}" - ) - prepared.append((p, provider, None, error)) - continue - if built is None: - prepared.append((p, provider, None, "stt_audio_not_configured")) - continue - prepared.append((p, provider, built, None)) - return prepared + +def _store_last_job_id(job_id: UUID) -> None: + try: + _redis_client.set(_LAST_JOB_ID_KEY, str(job_id)) + except redis.RedisError as e: + logger.error( + f"[_store_last_job_id] Redis SET failed | job_id: {job_id}, error: {e}" + ) -def run_probes() -> dict[str, Any]: +def run_health_probe_tick() -> dict[str, Any]: + """Check the previous probe's result, then fire the next one round-robin.""" org_id = settings.HEALTH_PROBE_ORG_ID project_id = settings.HEALTH_PROBE_PROJECT_ID if org_id is None or project_id is None: logger.warning( - "[run_probes] Health probe org/project not configured — skipping" + "[run_health_probe_tick] Health probe org/project not configured — skipping" ) - return {"skipped": True, "reason": "health_probe_org_or_project_not_set"} + return { + "enqueued": False, + "job_id": None, + "probe_index": None, + "previous_job_status": None, + } - logger.info( - f"[run_probes] Starting | probes: {len(_PROBES)}, " - f"org_id: {org_id}, project_id: {project_id}" - ) + previous_status = _check_previous_probe(project_id) + _capture_previous_result_checkin(previous_status) + + index = _claim_next_probe_index() + probe = _PROBES[index] + request = _build_probe_request(probe, index) - # Session covers only preparation (credential lookup + config transform); - # it must be closed before the slow external provider calls below. with Session(engine) as session: - prepared = _prepare_probes(session, org_id=org_id, project_id=project_id) + job_id = start_job( + db=session, + request=request, + project_id=project_id, + organization_id=org_id, + ) - started = time.perf_counter() - with ThreadPoolExecutor(max_workers=_PROBE_WORKERS) as pool: - results = list(pool.map(lambda pp: _run_probe(*pp), prepared)) - elapsed_ms = int((time.perf_counter() - started) * 1000) + _store_last_job_id(job_id) - ok_count = sum(1 for r in results if r["ok"]) logger.info( - f"[run_probes] Completed | total: {len(results)}, ok: {ok_count}, " - f"failed: {len(results) - ok_count}, elapsed_ms: {elapsed_ms}" + f"[run_health_probe_tick] Fired probe | provider: {probe.provider}, " + f"model: {probe.model}, modality: {probe.modality}, job_id: {job_id}, " + f"previous_job_status: {previous_status}" ) return { - "elapsed_ms": elapsed_ms, - "total": len(results), - "ok": ok_count, - "failed": len(results) - ok_count, - "results": results, + "enqueued": True, + "job_id": job_id, + "probe_index": index, + "previous_job_status": previous_status.value if previous_status else None, } - - -def execute_health_probes() -> dict[str, Any]: - """Run the probes wrapped in Sentry cron check-ins. - - The check-in happens here (not in the cron route) so the monitor reflects - actual probe results rather than enqueue success. - """ - check_in_id = capture_checkin( - monitor_slug=HEALTH_PROBES_MONITOR_SLUG, - status=MonitorStatus.IN_PROGRESS, - monitor_config=HEALTH_PROBES_MONITOR_CONFIG, - ) - try: - result = run_probes() - except Exception: - capture_checkin( - check_in_id=check_in_id, - monitor_slug=HEALTH_PROBES_MONITOR_SLUG, - status=MonitorStatus.ERROR, - ) - raise - - ok = not result.get("skipped") and result.get("failed") == 0 - capture_checkin( - check_in_id=check_in_id, - monitor_slug=HEALTH_PROBES_MONITOR_SLUG, - status=MonitorStatus.OK if ok else MonitorStatus.ERROR, - ) - return result - - -def main() -> None: - """Manual smoke test: `uv run python -m app.services.health_probes`. - - Calls run_probes directly (no Sentry check-ins) against the configured - HEALTH_PROBE_ORG_ID/PROJECT_ID — real provider calls, real credentials. - """ - import json - - logging.basicConfig(level=logging.INFO) - print(json.dumps(run_probes(), indent=2)) - - -if __name__ == "__main__": - main() diff --git a/backend/app/tests/api/routes/test_cron_health_probes.py b/backend/app/tests/api/routes/test_cron_health_probes.py index b92b2ab25..8ccdc897a 100644 --- a/backend/app/tests/api/routes/test_cron_health_probes.py +++ b/backend/app/tests/api/routes/test_cron_health_probes.py @@ -1,5 +1,6 @@ -from types import SimpleNamespace +from typing import Any from unittest.mock import patch +from uuid import uuid4 from fastapi.testclient import TestClient @@ -7,24 +8,34 @@ from app.tests.utils.auth import TestAuthContext -def test_health_probes_cron_enqueues_and_returns_task_id( +def _fake_tick_result(**overrides: Any) -> dict[str, Any]: + result = { + "enqueued": True, + "job_id": str(uuid4()), + "probe_index": 4, + "previous_job_status": "SUCCESS", + } + result.update(overrides) + return result + + +def test_health_probes_cron_runs_tick_and_returns_result( client: TestClient, superuser_api_key: TestAuthContext, ) -> None: - fake_async_result = SimpleNamespace(id="test-task-id") + canned = _fake_tick_result() with patch( - "app.api.routes.cron.run_health_probes.delay", - return_value=fake_async_result, - ) as delay_mock: + "app.api.routes.cron.run_health_probe_tick", return_value=canned + ) as tick_mock: response = client.get( f"{settings.API_V1_STR}/cron/health-probes", headers={"X-API-KEY": superuser_api_key.key}, ) assert response.status_code == 200 - assert response.json() == {"enqueued": True, "task_id": "test-task-id"} - delay_mock.assert_called_once_with() + assert response.json() == canned + tick_mock.assert_called_once_with() def test_health_probes_cron_requires_superuser( @@ -32,9 +43,9 @@ def test_health_probes_cron_requires_superuser( user_api_key: TestAuthContext, ) -> None: with patch( - "app.api.routes.cron.run_health_probes.delay", - return_value=SimpleNamespace(id="should-not-run"), - ) as delay_mock: + "app.api.routes.cron.run_health_probe_tick", + return_value=_fake_tick_result(), + ) as tick_mock: response = client.get( f"{settings.API_V1_STR}/cron/health-probes", headers={"X-API-KEY": user_api_key.key}, @@ -42,20 +53,18 @@ def test_health_probes_cron_requires_superuser( assert response.status_code == 403 assert "Insufficient permissions" in response.json()["error"] - delay_mock.assert_not_called() + tick_mock.assert_not_called() -def test_health_probes_cron_requires_authentication( - client: TestClient, -) -> None: +def test_health_probes_cron_requires_authentication(client: TestClient) -> None: with patch( - "app.api.routes.cron.run_health_probes.delay", - return_value=SimpleNamespace(id="should-not-run"), - ) as delay_mock: + "app.api.routes.cron.run_health_probe_tick", + return_value=_fake_tick_result(), + ) as tick_mock: response = client.get(f"{settings.API_V1_STR}/cron/health-probes") assert response.status_code in (401, 403) - delay_mock.assert_not_called() + tick_mock.assert_not_called() def test_health_probes_cron_not_in_openapi_schema(client: TestClient) -> None: diff --git a/backend/app/tests/celery/test_run_health_probes.py b/backend/app/tests/celery/test_run_health_probes.py deleted file mode 100644 index 64a30e2ee..000000000 --- a/backend/app/tests/celery/test_run_health_probes.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Any -from unittest.mock import patch - -from app.celery.tasks import job_execution - - -def test_run_health_probes_task_returns_execute_result() -> None: - canned: dict[str, Any] = { - "elapsed_ms": 42, - "total": 3, - "ok": 3, - "failed": 0, - "results": [], - } - - # the task lazy-imports execute_health_probes, so patch it at its source module - with patch( - "app.services.health_probes.execute_health_probes", - return_value=canned, - ) as execute_mock: - result = job_execution.run_health_probes.apply(args=[]).get() - - assert result == canned - execute_mock.assert_called_once_with() diff --git a/backend/app/tests/services/test_health_probes.py b/backend/app/tests/services/test_health_probes.py index 96efc7276..be614747b 100644 --- a/backend/app/tests/services/test_health_probes.py +++ b/backend/app/tests/services/test_health_probes.py @@ -1,26 +1,25 @@ -from pathlib import Path +import threading from types import TracebackType from typing import Any +from unittest.mock import patch +from uuid import UUID, uuid4 import pytest from sqlmodel import Session -from app.core.audio_utils import AudioRef from app.core.config import settings -from app.models.llm import NativeCompletionConfig, QueryParams +from app.crud.jobs import JobCrud +from app.models.job import JobStatus, JobType, JobUpdate +from app.models.llm.request import KaapiCompletionConfig from app.services import health_probes -from app.services.health_probes import ( - HEALTH_PROBES_MONITOR_CONFIG, - HEALTH_PROBES_MONITOR_SLUG, - _PROBES, - execute_health_probes, - run_probes, -) +from app.services.health_probes import _PROBES, _build_probe_request +from app.services.llm.mappers import transform_kaapi_config_to_native +from app.tests.utils.test_data import create_test_project class _NonClosingSession: - """Stands in for `Session(engine)` inside run_probes, yielding the - conftest transactional session without closing it on __exit__.""" + """Stands in for `Session(engine)` inside health_probes, backed by the + conftest transactional `db` session instead of closing a real one.""" def __init__(self, session: Session): self._session = session @@ -37,344 +36,197 @@ def __exit__( return False -class _FakeProvider: - def __init__( - self, - response: Any = None, - error: str | None = None, - raise_exc: Exception | None = None, - ): - self._response = response - self._error = error - self._raise_exc = raise_exc - self.calls: list[dict[str, Any]] = [] - - def execute( - self, - *, - completion_config: NativeCompletionConfig, - query: QueryParams, - resolved_input: str | AudioRef, - ) -> tuple[Any, str | None]: - self.calls.append( - { - "completion_config": completion_config, - "query": query, - "resolved_input": resolved_input, - } - ) - if self._raise_exc is not None: - raise self._raise_exc - return self._response, self._error - - -@pytest.fixture -def configured_probe_settings(db: Session, monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", 1) - monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", 1) - # run_probes opens its own Session(engine); point it at the conftest - # transactional session so nothing leaks past the test. - monkeypatch.setattr( - health_probes, "Session", lambda _engine: _NonClosingSession(db) - ) - +class _FakeRedis: + """In-memory stand-in for `_redis_client`. `incr` is lock-protected so it + actually replicates Redis's atomicity for the concurrency test below.""" -class TestSkipWhenNotConfigured: - def test_returns_skipped_when_org_id_missing( - self, monkeypatch: pytest.MonkeyPatch - ) -> None: - monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", None) - monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", 1) - monkeypatch.setattr( - health_probes, - "Session", - lambda _engine: pytest.fail("no session must be opened when skipping"), - ) + def __init__(self) -> None: + self.store: dict[str, str] = {} + self._lock = threading.Lock() - result = run_probes() + def get(self, key: str) -> str | None: + return self.store.get(key) - assert result == { - "skipped": True, - "reason": "health_probe_org_or_project_not_set", - } + def set(self, key: str, value: Any) -> None: + self.store[key] = str(value) - def test_returns_skipped_when_project_id_missing( - self, monkeypatch: pytest.MonkeyPatch - ) -> None: - monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", 1) - monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", None) - monkeypatch.setattr( - health_probes, - "get_llm_provider", - lambda **_k: pytest.fail("provider must not be built"), - ) + def incr(self, key: str) -> int: + with self._lock: + count = int(self.store.get(key, "0")) + 1 + self.store[key] = str(count) + return count - result = run_probes() - assert result["skipped"] is True - assert result["reason"] == "health_probe_org_or_project_not_set" +@pytest.fixture +def probe_env(db: Session, monkeypatch: pytest.MonkeyPatch): + project = create_test_project(db) + monkeypatch.setattr(settings, "HEALTH_PROBE_ORG_ID", project.organization_id) + monkeypatch.setattr(settings, "HEALTH_PROBE_PROJECT_ID", project.id) + monkeypatch.setattr( + health_probes, "Session", lambda _engine: _NonClosingSession(db) + ) + fake_redis = _FakeRedis() + monkeypatch.setattr(health_probes, "_redis_client", fake_redis) + return project, fake_redis -class TestRunProbesShape: - def test_all_probes_ok_returns_expected_structure( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None - ) -> None: - fake = _FakeProvider(response={"data": "pong"}, error=None) - monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - - result = run_probes() - - assert set(result.keys()) == { - "elapsed_ms", - "total", - "ok", - "failed", - "results", - } - assert isinstance(result["elapsed_ms"], int) - assert result["total"] == len(_PROBES) - assert result["ok"] == len(_PROBES) - assert result["failed"] == 0 - assert len(result["results"]) == len(_PROBES) - - for r in result["results"]: - assert set(r.keys()) == { - "endpoint", - "provider", - "modality", - "model", - "ok", - "latency_ms", - "error", - } - assert r["endpoint"] == "llm/call" - assert r["ok"] is True - assert r["error"] is None - assert isinstance(r["latency_ms"], int) - - # the config build must hand the provider a native config, not the Kaapi one - assert all( - isinstance(c["completion_config"], NativeCompletionConfig) - for c in fake.calls - ) +def _create_job(db: Session, project_id: int, status: JobStatus) -> UUID: + job = JobCrud(session=db).create(job_type=JobType.LLM_API, project_id=project_id) + JobCrud(session=db).update(job_id=job.id, job_update=JobUpdate(status=status)) + return job.id -class TestProviderInitFailure: - def test_get_llm_provider_value_error_marks_client_init_failed( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None +class TestFiresExactlyOneProbe: + def test_tick_enqueues_exactly_one_job( + self, probe_env: tuple[Any, _FakeRedis] ) -> None: - def _boom(**_kwargs: Any) -> _FakeProvider: - raise ValueError("no creds") + _, _fake_redis = probe_env + expected_job_id = uuid4() - monkeypatch.setattr(health_probes, "get_llm_provider", _boom) + with patch( + "app.services.health_probes.start_job", return_value=expected_job_id + ) as start_job_mock: + result = health_probes.run_health_probe_tick() - result = run_probes() + start_job_mock.assert_called_once() + assert result["enqueued"] is True + assert result["job_id"] == expected_job_id - assert result["ok"] == 0 - assert result["failed"] == len(_PROBES) - for r in result["results"]: - assert r["ok"] is False - assert r["error"] == "client_init_failed" - assert r["latency_ms"] is None - def test_get_llm_provider_runtime_error_marks_client_init_failed( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None +class TestRoundRobinRotation: + def test_index_advances_and_wraps_across_full_registry( + self, probe_env: tuple[Any, _FakeRedis] ) -> None: - monkeypatch.setattr( - health_probes, - "get_llm_provider", - lambda **_k: (_ for _ in ()).throw(RuntimeError("bad")), - ) - - result = run_probes() + seen_indexes = [] + with patch( + "app.services.health_probes.start_job", side_effect=lambda **_k: uuid4() + ): + for _ in range(len(_PROBES)): + result = health_probes.run_health_probe_tick() + seen_indexes.append(result["probe_index"]) - assert result["failed"] == len(_PROBES) - assert all(r["error"] == "client_init_failed" for r in result["results"]) - assert all(r["latency_ms"] is None for r in result["results"]) + assert seen_indexes == list(range(len(_PROBES))) + wrapped = health_probes.run_health_probe_tick() + assert wrapped["probe_index"] == 0 -class TestExecuteBehaviors: - def test_execute_raises_marks_error_with_exception_class_name( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + def test_concurrent_claims_never_collide_or_skip_a_slot( + self, probe_env: tuple[Any, _FakeRedis] ) -> None: - fake = _FakeProvider(raise_exc=TimeoutError("slow")) - monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - - result = run_probes() - - assert result["ok"] == 0 - for r in result["results"]: - assert r["ok"] is False - assert r["error"].startswith("TimeoutError") - assert "slow" in r["error"] - assert isinstance(r["latency_ms"], int) - - def test_provider_returns_none_response_uses_provided_error( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + # N concurrent claims must land on N distinct, evenly spread slots. + from concurrent.futures import ThreadPoolExecutor + + rounds = 5 + total_claims = rounds * len(_PROBES) + with ThreadPoolExecutor(max_workers=16) as pool: + claimed = list( + pool.map( + lambda _: health_probes._claim_next_probe_index(), + range(total_claims), + ) + ) + + counts = {i: claimed.count(i) for i in range(len(_PROBES))} + assert all(count == rounds for count in counts.values()), counts + + +class TestMissingRedisKeysDoNotFailTick: + def test_missing_index_key_defaults_to_zero( + self, db: Session, probe_env: tuple[Any, _FakeRedis] ) -> None: - fake = _FakeProvider(response=None, error="some_error") - monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - - result = run_probes() - - assert result["ok"] == 0 - assert result["failed"] == len(_PROBES) - for r in result["results"]: - assert r["ok"] is False - assert r["error"] == "some_error" - assert isinstance(r["latency_ms"], int) - - def test_provider_returns_none_response_and_no_error_defaults_no_response( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + project, fake_redis = probe_env + # last_job_id present (not a first-ever run), index key absent. + existing_job_id = _create_job(db, project.id, JobStatus.SUCCESS) + fake_redis.store[health_probes._LAST_JOB_ID_KEY] = str(existing_job_id) + + with patch( + "app.services.health_probes.start_job", return_value=uuid4() + ) as start_job_mock: + result = health_probes.run_health_probe_tick() + + start_job_mock.assert_called_once() + assert result["enqueued"] is True + assert result["probe_index"] == 0 + + def test_missing_last_job_id_key_skips_checkin_but_still_fires( + self, probe_env: tuple[Any, _FakeRedis] ) -> None: - fake = _FakeProvider(response=None, error=None) - monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - - result = run_probes() - - for r in result["results"]: - assert r["ok"] is False - assert r["error"] == "no_response" - - def test_provider_returns_response_marks_ok( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None + _, fake_redis = probe_env + fake_redis.store[health_probes._INDEX_KEY] = "2" + + with ( + patch( + "app.services.health_probes.start_job", return_value=uuid4() + ) as start_job_mock, + patch("app.services.health_probes.capture_checkin") as checkin_mock, + ): + result = health_probes.run_health_probe_tick() + + start_job_mock.assert_called_once() + checkin_mock.assert_not_called() + assert result["enqueued"] is True + assert result["probe_index"] == 2 + assert result["previous_job_status"] is None + + +class TestPreviousProbeCheckin: + def test_previous_job_failed_reports_error_checkin( + self, db: Session, probe_env: tuple[Any, _FakeRedis] ) -> None: - fake = _FakeProvider(response={"ok": 1}, error=None) - monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - - result = run_probes() - - assert result["ok"] == len(_PROBES) - for r in result["results"]: - assert r["ok"] is True - assert r["error"] is None - - -class TestSttAudioNotConfigured: - def test_missing_stt_audio_file_short_circuits_stt_probes( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None - ) -> None: - monkeypatch.setattr( - health_probes, "_STT_AUDIO_PATH", Path("/nonexistent/probe.ogg") + project, fake_redis = probe_env + failed_job_id = _create_job(db, project.id, JobStatus.FAILED) + fake_redis.store[health_probes._LAST_JOB_ID_KEY] = str(failed_job_id) + + with ( + patch("app.services.health_probes.start_job", return_value=uuid4()), + patch("app.services.health_probes.capture_checkin") as checkin_mock, + ): + result = health_probes.run_health_probe_tick() + + checkin_mock.assert_called_once() + assert ( + checkin_mock.call_args.kwargs["status"] == health_probes.MonitorStatus.ERROR ) - # reset the lazy-load cache so the missing path is actually read - monkeypatch.setattr(health_probes, "_stt_audio_bytes", None) - fake = _FakeProvider(response={"ok": 1}, error=None) - monkeypatch.setattr(health_probes, "get_llm_provider", lambda **_k: fake) - - result = run_probes() - - stt_results = [r for r in result["results"] if r["modality"] == "stt"] - assert stt_results, "expected at least one STT probe" - for r in stt_results: - assert r["ok"] is False - assert r["error"] == "stt_audio_not_configured" - # short-circuit happens before execute → no latency recorded - assert r["latency_ms"] is None - - non_stt = [r for r in result["results"] if r["modality"] != "stt"] - for r in non_stt: - assert r["ok"] is True - - -class TestProviderCaching: - def test_get_llm_provider_called_once_per_unique_provider( - self, monkeypatch: pytest.MonkeyPatch, configured_probe_settings: None - ) -> None: - seen_providers: list[str] = [] - - def _factory(**kwargs: Any) -> _FakeProvider: - seen_providers.append(kwargs["provider_type"]) - return _FakeProvider(response={"ok": 1}, error=None) - - monkeypatch.setattr(health_probes, "get_llm_provider", _factory) - - run_probes() - - unique_probe_providers = {p.provider for p in _PROBES} - # One factory call per unique provider name, not per probe - assert sorted(seen_providers) == sorted(unique_probe_providers) - assert len(seen_providers) < len(_PROBES) + assert result["previous_job_status"] == JobStatus.FAILED.value - -class TestExecuteHealthProbes: - @staticmethod - def _patch_checkin( - monkeypatch: pytest.MonkeyPatch, - ) -> list[dict[str, Any]]: - checkins: list[dict[str, Any]] = [] - - def _capture(**kwargs: Any) -> str: - checkins.append(kwargs) - return "checkin-123" - - monkeypatch.setattr(health_probes, "capture_checkin", _capture) - return checkins - - def test_ok_result_closes_checkin_with_ok( - self, monkeypatch: pytest.MonkeyPatch + def test_previous_job_success_reports_ok_checkin( + self, db: Session, probe_env: tuple[Any, _FakeRedis] ) -> None: - checkins = self._patch_checkin(monkeypatch) - canned = {"elapsed_ms": 1, "total": 2, "ok": 2, "failed": 0, "results": []} - monkeypatch.setattr(health_probes, "run_probes", lambda: canned) - - result = execute_health_probes() - - assert result == canned - assert len(checkins) == 2 - assert checkins[0] == { - "monitor_slug": HEALTH_PROBES_MONITOR_SLUG, - "status": health_probes.MonitorStatus.IN_PROGRESS, - "monitor_config": HEALTH_PROBES_MONITOR_CONFIG, - } - assert checkins[1] == { - "check_in_id": "checkin-123", - "monitor_slug": HEALTH_PROBES_MONITOR_SLUG, - "status": health_probes.MonitorStatus.OK, - } - - def test_failed_probes_close_checkin_with_error( - self, monkeypatch: pytest.MonkeyPatch - ) -> None: - checkins = self._patch_checkin(monkeypatch) - canned = {"elapsed_ms": 1, "total": 2, "ok": 1, "failed": 1, "results": []} - monkeypatch.setattr(health_probes, "run_probes", lambda: canned) - - result = execute_health_probes() - - assert result == canned - assert checkins[1]["status"] == health_probes.MonitorStatus.ERROR - assert checkins[1]["check_in_id"] == "checkin-123" - - def test_skipped_result_closes_checkin_with_error( - self, monkeypatch: pytest.MonkeyPatch - ) -> None: - checkins = self._patch_checkin(monkeypatch) - skipped = {"skipped": True, "reason": "health_probe_org_or_project_not_set"} - monkeypatch.setattr(health_probes, "run_probes", lambda: skipped) - - result = execute_health_probes() - - assert result == skipped - assert checkins[1]["status"] == health_probes.MonitorStatus.ERROR - - def test_run_probes_raising_sends_error_checkin_and_propagates( - self, monkeypatch: pytest.MonkeyPatch + project, fake_redis = probe_env + success_job_id = _create_job(db, project.id, JobStatus.SUCCESS) + fake_redis.store[health_probes._LAST_JOB_ID_KEY] = str(success_job_id) + + with ( + patch("app.services.health_probes.start_job", return_value=uuid4()), + patch("app.services.health_probes.capture_checkin") as checkin_mock, + ): + result = health_probes.run_health_probe_tick() + + checkin_mock.assert_called_once() + assert checkin_mock.call_args.kwargs["status"] == health_probes.MonitorStatus.OK + assert result["previous_job_status"] == JobStatus.SUCCESS.value + + +class TestProbeRegistryPayloadsAreValid: + # FR-8/FR-10/FR-11: every registry entry must resolve through the real + # Kaapi -> native mapper with zero warnings (catches e.g. Sarvam TTS + # missing `language`, ElevenLabs TTS missing `voice`). + + @pytest.mark.parametrize( + "probe", + _PROBES, + ids=[f"{p.provider}-{p.model}-{p.modality}" for p in _PROBES], + ) + def test_probe_config_resolves_with_no_mapper_warnings( + self, db: Session, probe: health_probes.Probe ) -> None: - checkins = self._patch_checkin(monkeypatch) - - def _boom() -> dict[str, Any]: - raise RuntimeError("probe explosion") + request = _build_probe_request(probe, index=0) - monkeypatch.setattr(health_probes, "run_probes", _boom) + kaapi_config = request.config.blob.completion # type: ignore[union-attr] + assert isinstance(kaapi_config, KaapiCompletionConfig) - with pytest.raises(RuntimeError, match="probe explosion"): - execute_health_probes() + _native_config, warnings = transform_kaapi_config_to_native( + session=db, kaapi_config=kaapi_config + ) - assert len(checkins) == 2 - assert checkins[0]["status"] == health_probes.MonitorStatus.IN_PROGRESS - assert checkins[1] == { - "check_in_id": "checkin-123", - "monitor_slug": HEALTH_PROBES_MONITOR_SLUG, - "status": health_probes.MonitorStatus.ERROR, - } + assert warnings == [] diff --git a/docs/wiki/INDEX.md b/docs/wiki/INDEX.md index 9bc299d34..4417c9d28 100644 --- a/docs/wiki/INDEX.md +++ b/docs/wiki/INDEX.md @@ -22,7 +22,7 @@ Deep design narrative lives in `docs/architecture/*.md`; open those only for des - [modules/responses.md](modules/responses.md) — OpenAI Responses API integration, conversations, threads, assistants. No deep-dive doc yet. - [modules/assessment.md](modules/assessment.md) — assessments and assessment runs. No deep-dive doc yet. - [modules/tenancy.md](modules/tenancy.md) — users, orgs, projects, API keys, onboarding, login. -- [modules/platform.md](modules/platform.md) — analytics, notifications, feature flags, languages, credentials, model config, cron. +- [modules/platform.md](modules/platform.md) — analytics, notifications, feature flags, languages, credentials, model config, cron (incl. round-robin health probes through the real `/llm/call` pipeline). ### Cross-cutting - [cross-cutting/auth.md](cross-cutting/auth.md) — JWT, API keys, org/project permission model. diff --git a/docs/wiki/modules/platform.md b/docs/wiki/modules/platform.md index 0f34e5d87..961394ef6 100644 --- a/docs/wiki/modules/platform.md +++ b/docs/wiki/modules/platform.md @@ -12,5 +12,5 @@ All paths relative to `backend/app/`. | Languages | `api/routes/languages.py` | `global.languages` (`models/language.py`) | `crud/language.py` | | Credentials | `api/routes/credentials.py` | `credential` (`models/credentials.py`) | `crud/credentials.py`; provider keys per org/project | | Model config | `api/routes/model_config.py` | `model_config` (`models/model_config.py`) | `crud/model_config.py` | -| Cron | `api/routes/cron.py` | — | triggers batch polling (`crud/evaluations/cron.py`) | +| Cron | `api/routes/cron.py` | — | triggers batch polling (`crud/evaluations/cron.py`); health probes (`services/health_probes.py`) fire one round-robin probe per tick through the real `/llm/call` pipeline (`services/llm/jobs.py::start_job`), rotation state in Redis (`health_probe:index`, `health_probe:last_job_id`), no dedicated table — result rides the `job` table | | Jobs | — | `job` (`models/job.py`), `batch_job` (`models/batch_job.py`) | `crud/jobs.py`, `crud/job/`, `services/job_monitoring.py` | diff --git a/features/health-probes/SRD.md b/features/health-probes/SRD.md new file mode 100644 index 000000000..e73af5646 --- /dev/null +++ b/features/health-probes/SRD.md @@ -0,0 +1,110 @@ +# Health Probes SRD + +## Introduction & Purpose + +This SRD redefines Kaapi's provider health probes so a probe run is a real, checkable test of the `POST /llm/call` path, not a call that only confirms a Celery task got enqueued. + +The current probe (`app/services/health_probes.py`) calls `provider.execute()` directly, bundles all ~13 provider/modality combinations into a single Celery task, and wraps the Sentry check-in around that same enqueue-only task. This bypasses `LLMCallConfig` resolution and the provider mappers entirely, so a malformed per-provider config (ElevenLabs' TTS param is `model_id`, not `model`; Sarvam's TTS/STT calls require a `language` param absent from the probe payload) never reaches validation and never flags. There is also no independent per-probe record: pass/fail exists only inside a single combined Sentry check-in for the whole batch. + +The feature produces, per cron tick: +- Exactly one probe fired through the real `/llm/call` job pipeline (config blob -> mapper -> provider), using the same `job` table record every production LLM call gets. +- A Sentry check-in that reflects the previous tick's actual job outcome (`SUCCESS`/`FAILED`), not just that a task was enqueued. + +**Phase 1:** round-robin one-probe-per-tick firing through `start_job`, previous-probe status check via the existing `job` table, Redis-held rotation state. +**Phase 2+:** none identified; the hardcoded probe registry is maintained by hand as providers/models change. + +Intent: the probe is a real end-to-end regression guard against config/mapper/backward-compat breaks, with provider uptime as a secondary signal, not the reverse. + +## Goals + +- A probe traverses the full `/llm/call` path (`LLMCallConfig` resolution, mapper, provider call) via the same job pipeline production traffic uses, not a direct provider client call. +- Malformed or incompatible per-provider params (e.g. a wrong param name, a missing required param) surface as a validation or job failure, because the probe now goes through the same config validation every real call goes through. +- The registry's ElevenLabs TTS and Sarvam TTS entries carry the provider-required Kaapi params (`voice` and `language` respectively) so those two probes pass, not merely fail loudly. +- Each cron tick tests one probe from the registry, round-robin, instead of all combinations at once. +- Sentry reflects the real outcome of a specific probe's job, not just that a Celery task was enqueued. +- A missing rotation-state key in Redis degrades to a logged, Sentry-visible entry and the flow continues; it never fails the cron tick. + +## Assumptions & Constraints + +- **Out of scope:** a probe results table or dashboard (the `job` table is the record of pass/fail); config storage for probes (each probe's config is hardcoded in its `LLMCallRequest` payload); alerting rules beyond the existing Sentry cron-monitor check-in pattern. +- **Cadence:** cron fires every `HEALTH_PROBE_INTERVAL_MINUTES` (~3); one probe per tick. With N probes in the registry, a given probe's effective retest cadence is `N * HEALTH_PROBE_INTERVAL_MINUTES`. +- **Rotation state, no new table:** the round-robin index and the last-fired job ID live in Redis (`REDIS_URL`, already Kaapi's Celery result backend), not Postgres. Keys: `health_probe:index` (advanced via atomic `INCR`, `mod` over registry length, so two overlapping ticks can never claim the same slot) and `health_probe:last_job_id`. +- **Registry:** the probe list stays a hardcoded Python list, same shape as the current `_PROBES` (provider, model, modality), plus an explicit per-entry `params` dict for any Kaapi param a provider's mapper requires beyond `model`. Concretely: the Sarvam TTS entry carries `language` (its mapper hard-requires it for `target_language_code`, `app/services/llm/mappers.py` `map_kaapi_to_sarvam_params`), and the ElevenLabs TTS entry carries `voice` (its mapper hard-requires it to resolve `voice_id`, `map_kaapi_to_elevenlabs_params`). Edited by hand as providers/models change (e.g. drop a model once Kaapi stops using it). +- **Reuse:** no new tables. The probe's job rides the existing `job` table (`JobType.LLM_API`) via `start_job`, the same entry point `POST /llm/call` uses. `HEALTH_PROBE_ORG_ID` / `HEALTH_PROBE_PROJECT_ID` (existing settings) scope the probe's tenant. +- **Cost:** each probe tick is a real, billed provider call against the configured health-probe org/project; this pollutes that org's usage aggregation by one call per tick. Accepted cost, the point of routing through the real pipeline is the end-to-end regression guard, not a free check. +- **No callback:** the probe's `LLMCallRequest` carries no `callback_url`. Result reading is by polling `Job.status` on the next tick, not by callback delivery, so there is nothing for a callback to add, and no SSRF-guard/domain concern to solve (see Design Decisions). + +## Detailed Design (Execution Flow) + +Each cron tick does two things in one request: resolve the previous tick's probe result, then fire the next one. + +### Cron tick: check previous, fire next + +--- + +**>> PLACE IMAGE HERE: `assets/flow-a.png`, cron tick, check previous probe result then fire the next.** +System-level sequence: the external scheduler, the Kaapi backend, Redis, Postgres, Sentry, the LLM call pipeline, and the provider. + +--- + +Resolution order: read `health_probe:last_job_id` from Redis first. If present, look up that `Job` row; `SUCCESS` means the LLM was actually invoked and returned, `FAILED` (including a provider-side error surfaced through the pipeline) or still `PENDING` past the tick means a real failure, and either drives the Sentry check-in status. If the key is missing (first run, or a Redis eviction), log it and continue without failing the tick, no check-in is possible for a probe that was never recorded. + +Rotation: claim `health_probe:index` via an atomic `INCR` (default to `0` on a missing key or a Redis error, logged, non-fatal), select `registry[index mod len(registry)]`, call `start_job` with that probe's hardcoded `LLMCallRequest`, then write the new job ID to `health_probe:last_job_id`. The probe travels through the identical pipeline a real `/llm/call` request does; a provider-side error or a config validation error both land the job in `FAILED`, which is what the next tick reports. + +## Functional Requirements (Testing) + +| ID | What (user-facing behavior) | Acceptance criteria | Status | +|----|-----------------------------|---------------------|--------| +| FR-1 | One probe fired per cron tick | A single `GET /cron/health-probes` invocation enqueues exactly one `LLMCallRequest` job, not all registry entries | Not Started | +| FR-2 | Probe uses the real LLM call pipeline | The enqueued job resolves through `LLMCallConfig` and the provider mapper (the same path `POST /llm/call` uses), not a direct provider client call | Not Started | +| FR-3 | Round-robin selection | Across consecutive ticks, the probe index advances by one (mod registry length) each time; after `len(registry)` ticks every registry entry has been fired exactly once | Not Started | +| FR-4 | Missing rotation key does not fail the tick | With `health_probe:index` absent from Redis, the tick still fires a probe (defaulting to index 0) and logs the miss | Not Started | +| FR-5 | Missing last-job key does not fail the tick | With `health_probe:last_job_id` absent from Redis, the tick skips the previous-result check (logs it), and still fires the next probe | Not Started | +| FR-6 | Real job failure reported | When the previous probe's `Job.status` is `FAILED` (including a provider-side error), the tick's Sentry check-in reports an error state, not OK | Not Started | +| FR-7 | Real job success reported | When the previous probe's `Job.status` is `SUCCESS`, the tick's Sentry check-in reports OK | Not Started | +| FR-8 | Malformed per-provider config now surfaces | A registry entry whose hardcoded config is invalid for that provider (e.g. a required or misnamed param) fails at config validation/mapper resolution and lands the job in `FAILED`, it is not silently swallowed | Not Started | +| FR-9 | Concurrent ticks never collide | Two overlapping calls to the index claim never return the same index; across N concurrent claims, every registry slot is claimed the same number of times | Not Started | +| FR-10 | Sarvam TTS probe carries the required `language` param | The Sarvam TTS registry entry's mapped native params include `target_language_code`; its job reaches the provider call instead of failing at mapper resolution with "Missing required 'language' parameter for TTS" | Not Started | +| FR-11 | ElevenLabs TTS probe carries the required `voice` param | The ElevenLabs TTS registry entry's mapped native params include `voice_id`; its job reaches the provider call instead of failing at mapper resolution with "Missing required 'voice' parameter for TTS" | Not Started | + +## Endpoints + +### `GET /cron/health-probes` (existing, behavior replaced) + +Still hidden from Swagger, still superuser-only. No longer enqueues a bespoke all-probes Celery task; instead runs the check-previous-then-fire-next tick described above and returns immediately once the next probe is enqueued. + +**Response:** + +```json +{ + "enqueued": true, + "job_id": "9c2e4d6f-1a2b-3c4d-5e6f-7a8b9c0d1e2f", + "probe_index": 4, + "previous_job_status": "SUCCESS" +} +``` + +`previous_job_status` is `null` when `health_probe:last_job_id` was missing (first tick, or the key expired). + +## Database Schema + +No new tables. The probe's per-tick result rides the existing `job` table (`models/job.py`), the same table every `/llm/call` request writes to; `JobType.LLM_API`, scoped to `HEALTH_PROBE_PROJECT_ID`. + +## Configuration + +| Setting | Type | Default | Description | +|---------|------|---------|-------------| +| HEALTH_PROBE_INTERVAL_MINUTES | int | 3 | Cron tick interval, one probe per tick | +| HEALTH_PROBE_ORG_ID | int \| None | existing | Org the probe's job is created under | +| HEALTH_PROBE_PROJECT_ID | int \| None | existing | Project the probe's job is created under | + +## Design Decisions / Known Limitations + +- **Probe fires through `start_job`, not `provider.execute()`.** This is the core fix: the old design's biggest gap was bypassing config resolution and mappers, which is exactly where the ElevenLabs/Sarvam param mismatches lived undetected. Routing through the same entry point as production traffic means a config-shape regression fails the probe the same way it would fail a real caller. +- **No probe-specific Sentry span inside a bespoke Celery task.** The previous design's Sentry instrumentation sat on the enqueue route, so it never saw the actual provider call. This redesign removes the need for that span entirely: the probe now runs inside the standard LLM job pipeline (already traced), and the check-in is driven by reading the `Job.status` a tick later, which is a stronger signal than a span around a single synchronous call. +- **Redis over a new table for rotation state.** Redis is already wired up as the Celery result backend with unused capacity; a probe-index table would duplicate what two keys already do, and rotation state has no need for query, audit, or FK/tenant isolation. +- **Atomic `INCR`, not GET-then-SET, for the rotation index.** A read-then-write pair lets two overlapping ticks read the same index, fire the same probe, and silently skip another registry entry for a cycle. `INCR` is one atomic Redis command, so concurrent callers always land on distinct, consecutive slots. +- **No callback_url, no callback endpoint.** An earlier pass added a dummy `POST /internal/health-probe-callback` on the assumption the pipeline needs a callback target and Kaapi's SSRF guard would reject `localhost`. Neither holds: `callback_url` on `LLMCallRequest` is optional, `Job.status` is set to `SUCCESS`/`FAILED` in `execute_job` unconditionally, and callback delivery is a best-effort side channel that never gates it. Since the probe already reads its result by polling `Job.status` on the next tick, the callback bought nothing, so `callback_url` is simply omitted. +- **Calling `start_job` directly, not `POST /llm/call` over HTTP.** `start_job` is exactly what the route calls after its two thin wrapper concerns (the auth dependency and callback SSRF validation, both irrelevant to a cron-triggered internal probe with no callback). Going over HTTP instead would add API-key provisioning, a self-referential network hop, and JSON (de)serialization, all to rebuild the same `LLMCallRequest` this call already builds in Python, for no additional coverage. +- **Known limitation:** if a probe's config becomes stale (a model retired, a param shape changed upstream) the registry must be edited and redeployed by hand, there is no self-healing or drift detection on the registry itself. +- **ElevenLabs and Sarvam TTS payloads are fixed, not just detected.** The prior probe passed only `model` for every provider; ElevenLabs TTS silently needs `voice` (to resolve `voice_id`) and Sarvam TTS silently needs `language` (to resolve `target_language_code`), both hard requirements in their respective mappers. Phase 1 adds these fields to the registry entries directly, so both probes are expected to pass on first tick, not merely fail loudly. The redesigned pipeline (routing through the real mapper) is what surfaces this class of gap at all; the registry fix is what closes it for these two entries specifically. diff --git a/features/health-probes/assets/flow-a.mmd b/features/health-probes/assets/flow-a.mmd new file mode 100644 index 000000000..ce38c8a81 --- /dev/null +++ b/features/health-probes/assets/flow-a.mmd @@ -0,0 +1,27 @@ +sequenceDiagram + participant Scheduler as External Scheduler + participant Cron as Kaapi backend (cron route) + participant Redis + participant DB as Postgres (job table) + participant Sentry + participant Celery as LLM call pipeline (Celery) + participant Provider as LLM Provider + + Scheduler->>Cron: GET /cron/health-probes + Cron->>Redis: GET last_job_id + alt key present + Cron->>DB: look up previous Job by id + DB-->>Cron: JobStatus (SUCCESS / FAILED / PENDING) + Cron->>Sentry: check-in reflecting previous probe's real status + else key missing + Cron->>Sentry: log entry, continue (no flow failure) + end + Cron->>Redis: INCR probe_index (atomic claim) + Cron->>Cron: pick probe = registry[index mod len(registry)] + Cron->>Celery: start_job(LLMCallRequest for probe, no callback_url) + Celery-->>Cron: job_id + Cron->>Redis: SET last_job_id + Cron-->>Scheduler: 200 OK (enqueued) + Celery->>Provider: resolved config + input (config -> mapper -> provider) + Provider-->>Celery: response or provider error + Celery->>DB: update Job status (SUCCESS / FAILED) diff --git a/features/health-probes/assets/flow-a.png b/features/health-probes/assets/flow-a.png new file mode 100644 index 0000000000000000000000000000000000000000..a2bf8ee6ae1509ed2f194296c0c470a1ef8261ce GIT binary patch literal 313795 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

Yf5Ohfm@f?PJI4nRH|b8`ZE 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

51Wha(<;loIYfOWE0}{7k>!0y;s&o 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

8K~;D8>m;2wX0!;k_f-ru)%>sFb+tVeMm)&tn~ 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 Date: Thu, 30 Jul 2026 21:58:50 +0530 Subject: [PATCH 11/11] Update backend/app/api/routes/cron.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- backend/app/api/routes/cron.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/backend/app/api/routes/cron.py b/backend/app/api/routes/cron.py index 9a95b721b..49e31bfe5 100644 --- a/backend/app/api/routes/cron.py +++ b/backend/app/api/routes/cron.py @@ -132,12 +132,17 @@ def health_probes_cron_job() -> dict[str, Any]: # Runs synchronously (no Celery task of its own) — the probe rides the # existing LLM_API job pipeline via `start_job`. logger.info("[health_probes_cron_job] Cron job invoked") - result = run_health_probe_tick() - logger.info( - f"[health_probes_cron_job] Tick complete | job_id: {result.get('job_id')}, " - f"probe_index: {result.get('probe_index')}" - ) - return result + try: + result = run_health_probe_tick() + logger.info( + f"[health_probes_cron_job] Tick complete | job_id: {result.get('job_id')}, " + f"probe_index: {result.get('probe_index')}" + ) + return result + except Exception as e: + logger.error(f"[health_probes_cron_job] Tick failed: {e}", exc_info=True) + sentry_sdk.capture_exception(e) + raise @router.get(