feat: enhance health check endpoint to report API, database, and cache status; add standalone session for health checks

This commit is contained in:
2026-06-12 20:39:10 +08:00
parent 922aa5d3d6
commit 52dcd97728
5 changed files with 54 additions and 11 deletions
+5
View File
@@ -0,0 +1,5 @@
{
"chat.tools.terminal.autoApprove": {
"cp": true
}
}
+13
View File
@@ -51,6 +51,19 @@ async def get_session() -> AsyncIterator[AsyncSession]:
raise
def open_session() -> AsyncSession:
"""Return a standalone async session (for health checks, scripts, etc.).
The caller uses ``async with`` to enter/exit::
async with open_session() as session:
await session.execute(...)
The session is automatically closed on exit of the ``async with`` block.
"""
return _session_factory()
# ── Valkey (Redis-compatible) ─────────────────────────────────────────────
_valkey: Redis | None = None
+28 -2
View File
@@ -1,10 +1,36 @@
"""Health-check endpoint."""
"""Health-check endpoint — reports status of the API, database, and cache."""
from __future__ import annotations
from fastapi import APIRouter
from sqlalchemy import text
from backend.core.database import get_valkey, open_session
router = APIRouter(tags=["health"])
@router.get("/api/health")
async def health_check() -> dict[str, str]:
return {"status": "ok"}
"""Return API, database, and Valkey health status."""
result: dict[str, str] = {"status": "ok"}
# ── PostgreSQL ─────────────────────────────────────────────────────────
try:
async with open_session() as session:
await session.execute(text("SELECT 1"))
result["database"] = "ok"
except Exception as exc:
result["database"] = f"error: {exc}"
result["status"] = "degraded"
# ── Valkey / Redis ────────────────────────────────────────────────────
try:
valkey = await get_valkey()
await valkey.ping()
result["cache"] = "ok"
except Exception as exc:
result["cache"] = f"error: {exc}"
result["status"] = "degraded"
return result
+6 -2
View File
@@ -21,10 +21,12 @@ services:
ports:
- "8000:8000"
environment:
# NOTE: URLs are hardcoded to container service names so that the
# host .env file (with localhost URLs) does NOT override them.
- LLM_BASE_URL=${LLM_BASE_URL:-http://host.docker.internal:11434/v1}
- LLM_MODEL=${LLM_MODEL:-llama}
- DATABASE_URL=${DATABASE_URL:-postgresql+asyncpg://agent_alpha:agent_alpha@postgres:5432/agent_alpha}
- VALKEY_URL=${VALKEY_URL:-redis://valkey:6379/0}
- DATABASE_URL=postgresql+asyncpg://agent_alpha:agent_alpha@postgres:5432/agent_alpha
- VALKEY_URL=redis://valkey:6379/0
restart: unless-stopped
depends_on:
postgres:
@@ -34,8 +36,10 @@ services:
# Uncomment to use a local .env file instead of env vars:
# env_file:
# - .env
# Podman: use host.containers.internal; Docker Desktop: host.docker.internal
extra_hosts:
- "host.docker.internal:host-gateway"
- "host.containers.internal:host-gateway"
# ── React Frontend (nginx) ──────────────────────────────────────
frontend:
+2 -7
View File
@@ -5,15 +5,10 @@ server {
root /usr/share/nginx/html;
index index.html;
# Podman/Docker DNS — forces runtime resolution so nginx picks up
# container IP changes after restarts.
resolver 10.89.6.1 valid=10s;
# ── API proxy ─────────────────────────────────────────────────
# Use a variable so nginx resolves DNS at runtime, not at startup.
set $backend_upstream http://backend:8000;
# Resolved at container startup (depends_on ensures backend is up).
location /api/ {
proxy_pass $backend_upstream;
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;