I'm developing web API server with FastAPI and SQLAlchemy 1.4
What I'm going to do is like
- Commit on the end of all path operation function implicitly if there is no error occured.
- When HTTPException is occured, rollback the transaction.
In short, how to make FastAPI's path operation function atomic like database transaction.
These code snippets are what I'm using from tiangolo's full-stack-fastapi-postgresql project (https://github.com/tiangolo/full-stack-fastapi-postgresql)
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db() -> Generator:
try:
db = SessionLocal()
yield db
finally:
db.close()
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
app = FastAPI()
@app.put("/users/{id}")
def update_user(
id: int,
new_name: str,
new_login_id: str,
db: Session = Depends(deps.get_db),
):
"""
Simple User update API
"""
user = db.query(User).filter(User.id == id).first()
if not user:
raise HTTPExecption(404, "User not found")
user.name = new_name
if db.query(User).filter(User.login_id == new_login_id).first():
# if login id is already exist, I want to rollback update name
raise HTTPExecption(409, "Already used login id")
user.login_id = new_login_id
db.add(user)
# db.commit()
# I don't want to write db.commit() at the end of every path operation func.
return
I've tried in several ways
First, using FastAPI (Starlette) Middleware
I can't find way to pass db (Session) to middleware
Second, Add db.commit() at get_db()'s finally block
db.commit() is called even HTTPException is raised.
So I tried to use FastAPI Error handler for calling db.rollback() when HTTPExecption is raised, but I can't find a way to pass db (Session) to error handler.
How can I acheive it?