Skip to content

Commit 69f3dc3

Browse files
committed
wip: add exception handler
1 parent d722504 commit 69f3dc3

File tree

5 files changed

+52
-87
lines changed

5 files changed

+52
-87
lines changed

app/database.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from rotoger import AppStructLogger
44
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
5-
5+
from sqlalchemy.exc import SQLAlchemyError
66
from app.config import settings as global_settings
77

88
logger = AppStructLogger().get_logger()
@@ -29,6 +29,11 @@ async def get_db() -> AsyncGenerator:
2929
try:
3030
yield session
3131
await session.commit()
32-
except Exception as e:
33-
await logger.aerror(f"Error getting database session: {e}")
34-
raise
32+
except Exception as ex:
33+
if isinstance(ex, SQLAlchemyError):
34+
# Re-raise SQLAlchemyError directly without handling
35+
raise
36+
else:
37+
# Handle other exceptions
38+
await logger.aerror(f"NonSQLAlchemyError: {repr(ex)}")
39+
raise # Re-raise after logging

app/exception_handlers.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from fastapi import Request
2+
from fastapi.responses import JSONResponse
3+
from sqlalchemy.exc import SQLAlchemyError
4+
import orjson
5+
from fastapi import FastAPI
6+
from rotoger import AppStructLogger
7+
8+
logger = AppStructLogger().get_logger()
9+
10+
async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError) -> JSONResponse:
11+
request_path = request.url.path
12+
try:
13+
raw_body = await request.body()
14+
request_body = orjson.loads(raw_body) if raw_body else None
15+
except orjson.JSONDecodeError:
16+
request_body = None
17+
18+
await logger.aerror(
19+
"Database error occurred",
20+
sql_error=repr(exc),
21+
request_url=request_path,
22+
request_body=request_body,
23+
)
24+
25+
return JSONResponse(
26+
status_code=500,
27+
content={"message": "A database error occurred. Please try again later."},
28+
)
29+
30+
def register_exception_handlers(app: FastAPI) -> None:
31+
"""Register all exception handlers with the FastAPI app."""
32+
app.add_exception_handler(SQLAlchemyError, sqlalchemy_exception_handler)

app/exceptions.py

Lines changed: 0 additions & 59 deletions
This file was deleted.

app/main.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
import asyncpg
55
from fastapi import Depends, FastAPI, Request
6-
from fastapi.responses import HTMLResponse, JSONResponse
6+
from fastapi.responses import HTMLResponse
77
from fastapi.templating import Jinja2Templates
88
from rotoger import AppStructLogger
9-
from sqlalchemy.exc import SQLAlchemyError
9+
1010

1111
from app.api.health import router as health_router
1212
from app.api.ml import router as ml_router
@@ -17,6 +17,7 @@
1717
from app.config import settings as global_settings
1818
from app.redis import get_redis
1919
from app.services.auth import AuthBearer
20+
from app.exception_handlers import register_exception_handlers
2021

2122
logger = AppStructLogger().get_logger()
2223
templates = Jinja2Templates(directory=Path(__file__).parent.parent / "templates")
@@ -62,18 +63,8 @@ def create_app() -> FastAPI:
6263
dependencies=[Depends(AuthBearer())],
6364
)
6465

65-
@app.exception_handler(SQLAlchemyError)
66-
async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError):
67-
await logger.aerror(
68-
"A database error occurred",
69-
sql_error=repr(exc),
70-
request_url=request.url.path,
71-
request_body=request.body,
72-
)
73-
return JSONResponse(
74-
status_code=500,
75-
content={"message": "A database error occurred. Please try again later."},
76-
)
66+
# Register exception handlers
67+
register_exception_handlers(app)
7768

7869
@app.get("/index", response_class=HTMLResponse)
7970
def get_index(request: Request):

app/models/base.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,11 @@ def __tablename__(self) -> str:
2020
return self.__name__.lower()
2121

2222
async def save(self, db_session: AsyncSession):
23-
try:
24-
db_session.add(self)
25-
await db_session.flush()
26-
await db_session.refresh(self)
27-
return self
28-
except SQLAlchemyError as ex:
29-
await logger.aerror(f"Error inserting instance of {self}: {repr(ex)}")
30-
raise # This will make the exception handler catch it
23+
db_session.add(self)
24+
await db_session.flush()
25+
await db_session.refresh(self)
26+
return self
27+
3128

3229
async def delete(self, db_session: AsyncSession):
3330
try:
@@ -61,5 +58,4 @@ async def save_or_update(self, db_session: AsyncSession):
6158
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
6259
detail=repr(exception),
6360
) from exception
64-
finally:
65-
await db_session.close()
61+

0 commit comments

Comments
 (0)