feat(infra): add launch readiness quick wins
Some checks failed
CI / ruff (push) Successful in 12s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

- Add mem_limit to all 6 app containers (db: 512m, redis: 128m,
  api: 512m, celery-worker: 512m, celery-beat: 128m, flower: 128m)
- Restrict Flower port to localhost (127.0.0.1:5555:5555)
- Add PostgreSQL and Redis health checks to /health/ready endpoint
  with individual check details (name, status, latency)
- Add scaling guide with metrics, thresholds, Hetzner pricing
- Add server verification script (12 infrastructure checks)
- Update hetzner-server-setup.md with progress and pending tasks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 10:24:20 +01:00
parent 8ee8c398ce
commit 10fdf91dfa
6 changed files with 604 additions and 5 deletions

View File

@@ -531,12 +531,10 @@ async def readiness_check() -> dict[str, Any]:
Kubernetes readiness probe endpoint.
Returns 200 if the application is ready to serve traffic.
Includes individual check details with name, status, and latency.
"""
result = health_registry.run_all()
return {
"status": "ready" if result.status != HealthStatus.UNHEALTHY else "not_ready",
"health": result.status.value,
}
return result.to_dict()
@health_router.get("/metrics")
@@ -568,6 +566,44 @@ async def external_tools_endpoint() -> dict[str, str | None]:
# =============================================================================
def _register_infrastructure_health_checks() -> None:
"""Register health checks for core infrastructure (PostgreSQL, Redis)."""
from .config import settings
@health_registry.register("database")
def check_database() -> HealthCheckResult:
try:
from .database import engine
with engine.connect() as conn:
from sqlalchemy import text
conn.execute(text("SELECT 1"))
return HealthCheckResult(name="database", status=HealthStatus.HEALTHY)
except Exception as e:
return HealthCheckResult(
name="database",
status=HealthStatus.UNHEALTHY,
message=str(e),
)
@health_registry.register("redis")
def check_redis() -> HealthCheckResult:
try:
import redis
r = redis.from_url(settings.redis_url, socket_connect_timeout=2)
r.ping()
r.close()
return HealthCheckResult(name="redis", status=HealthStatus.HEALTHY)
except Exception as e:
return HealthCheckResult(
name="redis",
status=HealthStatus.UNHEALTHY,
message=str(e),
)
def init_observability(
enable_metrics: bool = False,
sentry_dsn: str | None = None,
@@ -587,6 +623,9 @@ def init_observability(
"""
logger.info("Initializing observability stack...")
# Register infrastructure health checks
_register_infrastructure_health_checks()
# Enable metrics if requested
if enable_metrics:
metrics_registry.enable()