wip: crud refactor

This commit is contained in:
grillazz 2025-08-23 17:53:18 +02:00
parent 93f2e66bd0
commit d722504e55
6 changed files with 30 additions and 31 deletions

View File

@ -116,5 +116,5 @@ async def update_stuff(
db_session: AsyncSession = Depends(get_db),
):
stuff = await Stuff.find(db_session, name)
await stuff.update(db_session, **payload.model_dump())
await stuff.update(**payload.model_dump())
return stuff

View File

@ -28,6 +28,7 @@ async def get_db() -> AsyncGenerator:
# logger.debug(f"ASYNC Pool: {engine.pool.status()}")
try:
yield session
await session.commit()
except Exception as e:
await logger.aerror(f"Error getting database session: {e}")
raise

View File

@ -3,9 +3,10 @@ from pathlib import Path
import asyncpg
from fastapi import Depends, FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from rotoger import AppStructLogger
from sqlalchemy.exc import SQLAlchemyError
from app.api.health import router as health_router
from app.api.ml import router as ml_router
@ -61,6 +62,19 @@ def create_app() -> FastAPI:
dependencies=[Depends(AuthBearer())],
)
@app.exception_handler(SQLAlchemyError)
async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError):
await logger.aerror(
"A database error occurred",
sql_error=repr(exc),
request_url=request.url.path,
request_body=request.body,
)
return JSONResponse(
status_code=500,
content={"message": "A database error occurred. Please try again later."},
)
@app.get("/index", response_class=HTMLResponse)
def get_index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})

View File

@ -20,64 +20,46 @@ class Base(DeclarativeBase):
return self.__name__.lower()
async def save(self, db_session: AsyncSession):
"""
:param db_session:
:return:
"""
try:
db_session.add(self)
await db_session.commit()
await db_session.flush()
await db_session.refresh(self)
return self
except SQLAlchemyError as ex:
await logger.aerror(f"Error inserting instance of {self}: {repr(ex)}")
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex)
) from ex
raise # This will make the exception handler catch it
async def delete(self, db_session: AsyncSession):
"""
:param db_session:
:return:
"""
try:
await db_session.delete(self)
await db_session.commit()
return True
except SQLAlchemyError as ex:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex)
) from ex
async def update(self, db: AsyncSession, **kwargs):
"""
:param db:
:param kwargs
:return:
"""
async def update(self, **kwargs):
try:
for k, v in kwargs.items():
setattr(self, k, v)
return await db.commit()
return True
except SQLAlchemyError as ex:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=repr(ex)
) from ex
async def save_or_update(self, db: AsyncSession):
async def save_or_update(self, db_session: AsyncSession):
try:
db.add(self)
return await db.commit()
db_session.add(self)
await db_session.flush()
return True
except IntegrityError as exception:
if isinstance(exception.orig, UniqueViolationError):
return await db.merge(self)
return await db_session.merge(self)
else:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=repr(exception),
) from exception
finally:
await db.close()
await db_session.close()

View File

@ -7,7 +7,9 @@ config = ConfigDict(from_attributes=True)
class RandomStuff(BaseModel):
chaos: dict[str, Any] = Field(..., description="JSON data for chaos field")
chaos: dict[str, Any] = Field(
..., description="Pretty chaotic JSON data can be added here..."
)
class StuffSchema(BaseModel):

View File