Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions agents/hyperhealth/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,8 @@ EXPOSE 8090
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=5 \
CMD curl -f http://localhost:8090/health || exit 1

# Run migrations on container start: upgrade head, fallback to stamp if needed
CMD ["sh", "-c", "alembic upgrade head || alembic stamp 001 && exec uvicorn main:app --host 0.0.0.0 --port 8090 --workers 2"]
# Migrate once, here, before uvicorn forks its workers. Never `|| alembic stamp`:
# 001 is head, so stamping on failure marks an unmigrated DB as fully migrated and
# every later `upgrade head` becomes a no-op. On failure we exit; compose has
# restart: unless-stopped and waits for postgres to be healthy, so it retries.
CMD ["sh", "-c", "alembic upgrade head && exec uvicorn main:app --host 0.0.0.0 --port 8090 --workers 2"]
23 changes: 5 additions & 18 deletions agents/hyperhealth/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import os
import sys
import uuid
import subprocess
from contextlib import asynccontextmanager
from datetime import datetime, timedelta
from pathlib import Path
Expand Down Expand Up @@ -105,23 +104,11 @@ def _get_session_factory():
async def lifespan(app: FastAPI):
log.info("hyperhealth.startup", environment=ENVIRONMENT)
engine = _get_engine()

# Run Alembic migrations on startup
try:
result = subprocess.run(
["alembic", "upgrade", "head"],
cwd=_HERE,
capture_output=True,
text=True,
timeout=30
)
if result.returncode == 0:
log.info("hyperhealth.migrations_completed")
else:
log.warning("hyperhealth.migrations_warning", stderr=result.stderr)
except Exception as e:
log.warning("hyperhealth.migrations_error", error=str(e))


# Migrations run once in the container CMD, before uvicorn forks its
# workers. lifespan executes per worker, so running alembic here meant
# concurrent `upgrade head` calls racing each other on every boot.

log.info("hyperhealth.db_ready")
await _ping_healer()
yield
Expand Down
Loading