Skip to content

Commit fd102bc

Browse files
authored
feat: add an endpoint for health check (#50)
1 parent 2f74302 commit fd102bc

File tree

5 files changed

+49
-4
lines changed

5 files changed

+49
-4
lines changed

fastqueue/api.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import uvicorn
22
from fastapi import Depends, FastAPI, Request, status
3+
from fastapi.encoders import jsonable_encoder
34
from fastapi.responses import JSONResponse
45
from prometheus_fastapi_instrumentator import Instrumentator
56
from sqlalchemy.orm import Session
@@ -11,6 +12,7 @@
1112
CreateMessageSchema,
1213
CreateQueueSchema,
1314
CreateTopicSchema,
15+
HealthSchema,
1416
ListMessageSchema,
1517
ListQueueSchema,
1618
ListTopicSchema,
@@ -21,7 +23,7 @@
2123
TopicSchema,
2224
UpdateQueueSchema,
2325
)
24-
from fastqueue.services import MessageService, QueueService, TopicService
26+
from fastqueue.services import HealthService, MessageService, QueueService, TopicService
2527

2628
tags_metadata = [
2729
{
@@ -67,7 +69,8 @@ def already_exists_exception_handler(request: Request, exc: AlreadyExistsError):
6769

6870
@app.exception_handler(NotFoundError)
6971
def not_found_exception_handler(request: Request, exc: NotFoundError):
70-
return JSONResponse(status_code=status.HTTP_404_NOT_FOUND, content={"detail": exc.args[0]})
72+
response = jsonable_encoder(NotFoundSchema(detail=exc.args[0]))
73+
return JSONResponse(status_code=status.HTTP_404_NOT_FOUND, content=response)
7174

7275

7376
@app.post("/topics", response_model=TopicSchema, status_code=status.HTTP_201_CREATED, tags=["topics"])
@@ -206,10 +209,22 @@ def nack_message(message_id: str, session: Session = Depends(get_session)):
206209
return MessageService(session=session).nack(id=message_id)
207210

208211

212+
@app.get(
213+
"/health",
214+
response_model=HealthSchema,
215+
status_code=status.HTTP_200_OK,
216+
tags=["healthcheck"],
217+
responses={500: {"model": HealthSchema}},
218+
)
219+
def health(session: Session = Depends(get_session)):
220+
response = HealthService(session=session).check()
221+
status_code = status.HTTP_200_OK if response.success else status.HTTP_500_INTERNAL_SERVER_ERROR
222+
return JSONResponse(status_code=status_code, content=jsonable_encoder(response))
223+
224+
209225
def run_server():
210226
uvicorn.run(
211227
"fastqueue.api:app",
212-
debug=settings.debug,
213228
host=settings.server_host,
214229
port=settings.server_port,
215230
log_level=settings.log_level.lower(),

fastqueue/schemas.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,7 @@ class Config:
137137

138138
class ListMessageSchema(Schema):
139139
data: list[MessageSchema]
140+
141+
142+
class HealthSchema(Schema):
143+
success: bool

fastqueue/services.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from datetime import datetime, timedelta
33
from typing import Any
44

5+
from sqlalchemy import text
56
from sqlalchemy.exc import IntegrityError
67
from sqlalchemy.orm import Session
78

@@ -11,6 +12,7 @@
1112
CreateMessageSchema,
1213
CreateQueueSchema,
1314
CreateTopicSchema,
15+
HealthSchema,
1416
ListMessageSchema,
1517
ListQueueSchema,
1618
ListTopicSchema,
@@ -332,3 +334,14 @@ def nack(self, id: str) -> None:
332334
message.scheduled_at = now
333335
message.updated_at = now
334336
self.session.commit()
337+
338+
339+
class HealthService(Service):
340+
def check(self) -> HealthSchema:
341+
success = True
342+
try:
343+
self.session.query(text("1")).from_statement(text("SELECT 1")).all()
344+
except Exception:
345+
success = False
346+
347+
return HealthSchema(success=success)

tests/test_api.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,11 @@ def test_nack_message(session, message, client):
294294
response = client.put(f"/messages/{message.id}/nack")
295295

296296
assert response.status_code == status.HTTP_204_NO_CONTENT
297+
298+
299+
def test_health(session, client):
300+
response = client.get("/health")
301+
response_data = response.json()
302+
303+
assert response.status_code == status.HTTP_200_OK
304+
assert response_data == {"success": True}

tests/test_services.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
RedriveQueueSchema,
1414
UpdateQueueSchema,
1515
)
16-
from fastqueue.services import MessageService, QueueService, TopicService
16+
from fastqueue.services import HealthService, MessageService, QueueService, TopicService
1717
from tests.factories import MessageFactory, QueueFactory, TopicFactory
1818

1919

@@ -428,3 +428,8 @@ def test_message_service_nack_with_removed_message(session):
428428
assert session.query(Message).filter_by(id=id).count() == 0
429429
assert MessageService(session=session).nack(id=id) is None
430430
assert session.query(Message).filter_by(id=id).count() == 0
431+
432+
433+
def test_health_service(session):
434+
response = HealthService(session=session).check()
435+
assert response.success

0 commit comments

Comments
 (0)