I doing a POC on FastAPI with a Controller-Service-Repository architecture. Service and Repository are classes, with dependency injection done in the __init__
function like so:
(This is the architecture, above my paygrade)
Class MyService(IService):
def __init__(self, repository):
self.repository = MyRepository() # Dependency Injection
...
Clas MyRepository(IRepository):
def__init__(self):
... # May create Engine and Session
I’ve been following FastApi’s documentation on Relational Database, and this block of code is suggested:
# Dependency
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
This creates a fresh sqlalchemy session when called and closes the session when the request ends, to be injected to the path operator function so that we get a fresh session per request.
According to this answer by the creator of SQLAlchemy:
[T]he question is, what’s the difference between making a new Session() at various points versus just using one all the way through. The answer, not very much.
and
This practice (one session per request) ensures that the new request begins “clean”. If some objects from the previous request haven’t been garbage collected yet, and if maybe you’ve turned off “expire_on_commit”, maybe some state from the previous request is still hanging around, and that state might even be pretty old. If you’re careful to leave expire_on_commit turned on and to definitely call commit() or rollback() at request end, then it’s fine, but if you start with a brand new Session, then there’s not even any question that you’re starting clean.
Per my understanding, one-session-per-request
is not necessary if we use SQLAlchemy’s defaults and context managers, like so:
# create session and add objects
with Session(engine) as session:
session.add(some_object)
session.add(some_other_object)
session.commit()
By creating one-session-per-request
, a new MyService
instance and/or MyRepository
instance is created for each request. FastApi docs says that dependencies are “cached” and reused only in the same request. However, if we stick with SQLAlchemy’s doc, we can make my MyService
and MyRepository
singletons.
So why does FastApi docs recommend one-session-per-request?
Is the overheads of creating instances per request negligible? Is there something with asyncio that I’m unaware of? Something to do with threads or process perhaps?