Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to integrate with context managers? #868

Open
SergeAvgust opened this issue Mar 6, 2025 · 2 comments
Open

Impossible to integrate with context managers? #868

SergeAvgust opened this issue Mar 6, 2025 · 2 comments

Comments

@SergeAvgust
Copy link

SergeAvgust commented Mar 6, 2025

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

@ZipFile
Copy link
Contributor

ZipFile commented Mar 6, 2025

Hello. This is a known issue. Good news I'm working on solving it right now. ETA approximately this or next weekend.

@SergeAvgust
Copy link
Author

Thanks a lot for your time! Hope it goes well)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants