modern-python / that-depends

DI-framework, inspired by python-dependency-injector, but without wiring. Python 3.12 is supported
https://that-depends.readthedocs.io/
MIT License
133 stars 10 forks source link

Teardown in alphabetical order #62

Closed stkrizh closed 1 month ago

stkrizh commented 1 month ago

Hello!

I've noticed that the BaseContainer.tear_down method tears down resources in alphabetical order (due to the implementation of inspect.getmembers). This can sometimes cause errors if one resource depends on another.

For instance:

async def resource(name, **kwargs):
    print("init resource", name, "depends on", kwargs)
    yield name
    print(name, "closed")

class Container(BaseContainer):
    a = providers.AsyncResource(resource, "A")
    b = providers.AsyncResource(resource, "B", a=a)  # B depends on A

async def main():
    await Container.init_async_resources()
    print("...")
    await Container.tear_down()

if __name__ == "__main__":
    asyncio.run(main())

This code will print:

init resource A depends on {}
init resource B depends on {'a': 'A'}
...
A closed
B closed

Resource A closes before resource B, despite the fact that B depends on A. If there is code during the teardown of resource B that expects resource A to still be in a valid state (i.e., open), errors are highly likely to occur.

Wouldn't it be more appropriate to tear down resources in the order of dependency? In this case, B should be torn down first, followed by A.

lesnik512 commented 1 month ago

@stkrizh Hi! thank you, seems fair, I will try to fix

stkrizh commented 1 month ago

Thanks! If you need some help with it, I could try to contribute.

lesnik512 commented 1 month ago

@stkrizh would be great!

stkrizh commented 1 month ago

@lesnik512 Prepared changes. Take a look please.