Description
I am trying to integrate the latest version of the library in my project, and i have faced the issue i can't find a solution for - i cannot make the cleanup work for usage mid-function.
Most of the time my usage of containers/providers is highly conventional and matches FastAPI+SQLAlchemy example. So here's some simplified examples. The main container and the database containers are declared this way:
import example_routes
class DBManager:
"""Manages database connection and migrations."""
_engine: AsyncEngine = None
_sessionmaker: async_sessionmaker = None
... # connect and dispose logic
async def get_session():
async with DBManager._sessionmaker() as session:
session: AsyncSession
try:
yield session
await session.commit()
except Exception as e:
await session.rollback()
logger.critical(e)
raise
finally:
await session.close()
class DatabaseContainer(containers.DeclarativeContainer):
session_factory = providers.Resource(
get_session
)
transaction_service = providers.Factory(
TxService,
session=session_factory
)
class MainContainer(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[
example_routes
]
)
config = providers.Configuration()
db = providers.Container(
DatabaseContainer,
config=config.run
)
Meanwhile the usage mostly works like that:
@inject
async def some_business_logic(
tx_service: TxService = Closing[Provide[MainContainer.db.transaction_service]],
):
...
HOWEVER.
I have a function with a long execution time, which makes several calls to the database and each of these calls needs to be its own session (cause i update database records and need to do that in real-time).
When i need to use the service in some kind of limited span inside of a function, i encounter a bug(?) where it does not trigger cleanup after the session was used. i have tried several approaches and none of them seem to work. Here is what i want to do:
async def long_function():
async with MainContainer.db.transaction_service as service:
await service.funcion_a()
# session is commited and closed during cleanup
# more logic
async with MainContainer.db.transaction_service as service:
await service.function_b()
# new session is commited and closed during cleanup
I have tried creating service context managed functions, somewhat like below, but they do not trigger cleanup
@asynccontextmanager
@inject
async def get_tx_service_ctx(
tx_service: TxService = Closing[Provide[MainContainer.db.session_factory]]
) -> AsyncGenerator[TxService, None]:
# somewhy under contextmanager container provides a future
serv = await tx_service
yield serv
print(serv)
The print at the end is triggered, but the cleanup of a session doesn't seem to be. What should i do? Can i make some kind of a workaround for this? I can't seem to find an alternative way in the docs nor in the examples