diff --git a/apps/api/src/router.py b/apps/api/src/router.py index ef3e226c..2725a263 100644 --- a/apps/api/src/router.py +++ b/apps/api/src/router.py @@ -1,5 +1,6 @@ import os from fastapi import APIRouter, Depends +from src.routers import health from src.routers import usergroups from src.routers import dev, trail, users, auth, orgs, roles from src.routers.ai import ai @@ -42,6 +43,8 @@ if os.environ.get("CLOUD_INTERNAL_KEY"): dependencies=[Depends(cloud_internal.check_internal_cloud_key)], ) +v1_router.include_router(health.router, prefix="/health", tags=["health"]) + # Dev Routes v1_router.include_router( dev.router, diff --git a/apps/api/src/routers/health.py b/apps/api/src/routers/health.py new file mode 100644 index 00000000..68d78588 --- /dev/null +++ b/apps/api/src/routers/health.py @@ -0,0 +1,11 @@ +from fastapi import Depends, APIRouter +from sqlmodel import Session +from src.services.health.health import check_health +from src.core.events.database import get_db_session + + +router = APIRouter() + +@router.get("") +async def health(db_session: Session = Depends(get_db_session)): + return await check_health(db_session) \ No newline at end of file diff --git a/apps/api/src/services/health/__init__.py b/apps/api/src/services/health/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/api/src/services/health/health.py b/apps/api/src/services/health/health.py new file mode 100644 index 00000000..8daccbd9 --- /dev/null +++ b/apps/api/src/services/health/health.py @@ -0,0 +1,21 @@ +from fastapi import HTTPException +from sqlmodel import Session, select +from src.db.organizations import Organization + +async def check_database_health(db_session: Session) -> bool: + statement = select(Organization) + result = db_session.exec(statement) + + if not result: + return False + + return True + +async def check_health(db_session: Session) -> bool: + # Check database health + database_healthy = await check_database_health(db_session) + + if not database_healthy: + raise HTTPException(status_code=503, detail="Database is not healthy") + + return True diff --git a/apps/web/app/api/health/route.ts b/apps/web/app/api/health/route.ts new file mode 100644 index 00000000..182501ae --- /dev/null +++ b/apps/web/app/api/health/route.ts @@ -0,0 +1,39 @@ +export const dynamic = 'force-dynamic' // defaults to auto +export const revalidate = 0 + +import { NextResponse } from 'next/server'; +import { checkHealth } from '@services/utils/health'; + +export async function GET() { + const health = await checkHealth() + if (health.success === true) { + return NextResponse.json( + { + status: 'healthy', + timestamp: new Date().toISOString(), + health: health.data, + }, + { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + } + ) + } else { + return NextResponse.json( + { + status: 'unhealthy', + timestamp: new Date().toISOString(), + health: null, + error: health.HTTPmessage, + }, + { + status: 503, + headers: { + 'Content-Type': 'application/json', + }, + } + ); + } +} diff --git a/apps/web/app/orgs/[orgslug]/health/page.tsx b/apps/web/app/orgs/[orgslug]/health/page.tsx deleted file mode 100644 index e9d89171..00000000 --- a/apps/web/app/orgs/[orgslug]/health/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' - -function HealthPage() { - return ( -