Description
Hello ets-labs, I felt really great on this morning for applying this awesome tool!
I almost had been finishing organizing dependency injection with fastapi during today, but there was a issue when closing AsyncResouces with on_shutdown of FastAPI.
I am on Mac with python 3.11.4, current version of installed D.I. is 4.41.0.
This works unexpectedly, remaining unclosed session.
from dependency_injector import providers, containers, resources, wiring
from aiohttp import ClientSession
import asyncio
from fastapi import FastAPI
class AsyncHttpClient(resources.AsyncResource):
async def init(self) -> ClientSession:
return ClientSession()
async def shutdown(self, client_session: ClientSession | None):
if client_session is not None:
await client_session.close()
class Container(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[__name__]
)
async_resource = providers.Resource(AsyncHttpClient)
async def main():
container = Container()
await container.init_resources()
app = FastAPI(
on_shutdown=[container.shutdown_resources],
)
if __name__ == "__main__":
asyncio.run(main())
>>>
Unclosed client session
client_session: <aiohttp.client.ClientSession object at xxxxxxx>
Below is working clean, remaining no unclosed session.
from dependency_injector import providers, containers, resources, wiring
from aiohttp import ClientSession
import asyncio
from fastapi import FastAPI
class AsyncHttpClient(resources.AsyncResource):
async def init(self) -> ClientSession:
return ClientSession()
async def shutdown(self, client_session: ClientSession | None):
if client_session is not None:
await client_session.close()
class Container(containers.DeclarativeContainer):
wiring_config = containers.WiringConfiguration(
modules=[__name__]
)
async_resource = providers.Resource(AsyncHttpClient)
@wiring.inject
async def inner(client=wiring.Provide[Container.async_resource]):
resp = await client.get("https://ipconfig.io/json")
print(await resp.json())
async def main():
container = Container()
await container.init_resources()
app = FastAPI(
on_shutdown=[container.shutdown_resources],
)
if __name__ == "__main__":
asyncio.run(main())
The only difference is existence of injected function. If injected function is, it succeed to closing and vice versa.(Even, I am not using it)
I had tried making closing first for hours, so I could not find solution. Luckily, I tested another way and found the way.
Would you tell me any mechanism about this ?