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
2 changes: 1 addition & 1 deletion backend-api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies = [
"numpy>=2.0",
"bitsandbytes>=0.48.2",
"torchvision>=0.24.0",
"fastapi[standard]>=0.122.0",
"fastapi[standard]>=0.131.0",
"uvicorn[standard]>=0.38.0",
"httpx>=0.28.1",
"pyvips>=2.2.3",
Expand Down
4 changes: 4 additions & 0 deletions backend-api/src/api/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from api.models.health import HealthResponse, IndexVersionResponse, IndexVersionsResponse
from api.models.images import (
ImageIngestRequest,
ImageIngestResponse,
Expand All @@ -14,6 +15,9 @@
"ImageListResponse",
"ImageResponse",
"ImageStatus",
"HealthResponse",
"IndexVersionResponse",
"IndexVersionsResponse",
"JobListResponse",
"JobResponse",
"RebuildIndexRequest",
Expand Down
21 changes: 21 additions & 0 deletions backend-api/src/api/models/health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from __future__ import annotations

from pydantic import BaseModel, Field


class HealthResponse(BaseModel):
status: str = Field(description="Service health state")


class IndexVersionResponse(BaseModel):
version: str
embed_model: str | None = None
index_type: str | None = None
num_vectors: int | None = None
dimension: int | None = None
is_active: bool
created_at: str | None = None


class IndexVersionsResponse(BaseModel):
versions: list[IndexVersionResponse]
11 changes: 6 additions & 5 deletions backend-api/src/api/routers/health.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from __future__ import annotations

import structlog
from fastapi import APIRouter, status
from fastapi.responses import JSONResponse
from fastapi import APIRouter, Response, status
from sqlalchemy import text
from temporalio.client import Client
from temporalio.contrib.pydantic import pydantic_data_converter

from api.models.health import HealthResponse
from shared.config import settings
from shared.db import get_engine
from shared.services.storage import get_storage_service
Expand Down Expand Up @@ -49,8 +49,8 @@ async def _check_temporal() -> bool:
return False


@router.get("/live")
async def healthcheck() -> JSONResponse:
@router.get("/live", response_model=HealthResponse)
async def healthcheck(response: Response) -> HealthResponse:
pg_ok = _check_postgres()
s3_ok = _check_s3()
temporal_ok = await _check_temporal()
Expand All @@ -67,4 +67,5 @@ async def healthcheck() -> JSONResponse:

status_code = status.HTTP_200_OK if healthy else status.HTTP_503_SERVICE_UNAVAILABLE

return JSONResponse(status_code=status_code, content={"status": "ok" if healthy else "degraded"})
response.status_code = status_code
return HealthResponse(status="ok" if healthy else "degraded")
29 changes: 15 additions & 14 deletions backend-api/src/api/routers/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from api.auth import AdminRequired
from api.deps import DbSession, TemporalClientDep
from api.models.health import IndexVersionResponse, IndexVersionsResponse
from api.models.jobs import JobListResponse, JobResponse, RebuildIndexRequest
from shared.config import settings
from shared.models import IndexBuild, Job, JobStatus, JobType
Expand Down Expand Up @@ -136,25 +137,25 @@ async def list_jobs(
)


@router.get("/indexes/versions")
@router.get("/indexes/versions", response_model=IndexVersionsResponse)
async def list_index_versions(
_auth: AdminRequired,
db: DbSession,
limit: int = Query(default=10, ge=1, le=50),
) -> dict:
) -> IndexVersionsResponse:
builds = db.query(IndexBuild).order_by(IndexBuild.created_at.desc()).limit(limit).all()

return {
"versions": [
{
"version": b.version,
"embed_model": b.embed_model,
"index_type": b.index_type,
"num_vectors": b.num_vectors,
"dimension": b.dimension,
"is_active": b.is_active,
"created_at": b.created_at.isoformat() if b.created_at else None,
}
return IndexVersionsResponse(
versions=[
IndexVersionResponse(
version=b.version,
embed_model=b.embed_model,
index_type=b.index_type,
num_vectors=b.num_vectors,
dimension=b.dimension,
is_active=b.is_active,
created_at=b.created_at.isoformat() if b.created_at else None,
)
for b in builds
]
}
)
107 changes: 104 additions & 3 deletions backend-api/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading