-
- Notifications
You must be signed in to change notification settings - Fork 339
Description
Hi! I'm trying to handle SQLAlchemy sessions as a resource provider instead of using FastAPI's built-in Depends.
Let me share some code:
The database class:
class Database: """Class to handle database connections and sessions""" def __init__(self, db_url: str, **kwargs): """Initialize the Database class with a database URL and optional keyword arguments""" self.db_url = db_url self.engine = create_engine(self.db_url, **kwargs, echo=settings.DEBUG_MODE, connect_args={"check_same_thread": False}, pool_size=0) self.local_session = sessionmaker(autocommit=False, autoflush=False, bind=self.engine) @contextmanager def session(self): """Context manager to handle sessions""" session: Session = self.local_session() try: yield session except Exception as e: session.rollback() finally: session.close()The main container where I create these resources:
def get_db_session(session_factory): with session_factory() as db: yield db class AppContainer(containers.DeclarativeContainer): """Container to serve all the containers related to the app""" # ..... other injections # Setup container for talent services db = providers.Factory(Database, db_url=settings.DB_URL) db_sess = providers.Resource(get_db_session, session_factory=db.provided.session) user_container = providers.Container( UserContainer, # and this container has "UserService" that also uses the db session dependency db_sess=db_sess, ) # .... So, I inject the session into the services directly (or in the future in one repository). I don't like injecting the session into the routers directly that's why I prefer not using the FastAPI Depends.
The code provided works as expected, it creates 1 session per request and then closes it, the thing is that this doesn't work in a concurrent environment, I made some local testing with locust, and once I start having many requests executing with multi-threads (I'm using sync endpoints), the sessions don't work as expected, it seems that the same session is being used in more than 1 request at the same time, so I guess this is something that we could solve if we had something like FactoryResource instead of just a Resource that works as a Singleton. I tried to implement this myself by creating a CustomProvider but I couldn't make it, so if anyone has any advice I'd appreciate it.
P.S: I checked all the related issues regarding FastAPI and SQLAlchemy sessions in this repo and tried some approaches but none of them worked correctly