Skip to content

Commit 44b703e

Browse files
committed
add db healthcheck endpoint
1 parent f4cea6d commit 44b703e

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

app/routers/api.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import qrcode
55
from fastapi import APIRouter, Depends, HTTPException
66
from fastapi.responses import RedirectResponse, StreamingResponse
7-
from sqlalchemy.exc import IntegrityError
7+
from sqlalchemy import text
8+
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
89
from sqlalchemy.ext.asyncio import AsyncSession
910

1011
from app.config import BASE_URL, MAX_TTL_HOURS
@@ -77,6 +78,14 @@ async def shorten_url(data: ShortenRequest, session: AsyncSession = Depends(get_
7778
short_code=code,
7879
)
7980

81+
@router.get("/api/health")
82+
async def health(session: AsyncSession = Depends(get_session)):
83+
try:
84+
await session.execute(text("SELECT 1"))
85+
except SQLAlchemyError:
86+
raise HTTPException(status_code=503, detail="database unavailable")
87+
return {"status": "ok"}
88+
8089
@router.get("/api/stats/{code}", response_model=LinkStats)
8190
async def get_stats(code: str, session: AsyncSession = Depends(get_session)):
8291
link = await find_link(session, code)

tests/test_api.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
from conftest import test_session as db_session_factory
99

1010

11+
@pytest.mark.asyncio
12+
async def test_health_ok(client):
13+
res = await client.get("/api/health")
14+
assert res.status_code == 200
15+
assert res.json() == {"status": "ok"}
16+
17+
1118
@pytest.mark.asyncio
1219
async def test_shorten_url(client):
1320
res = await client.post("/api/shorten", json={"url": "https://example.com"})

0 commit comments

Comments
 (0)