Open cpvandehey opened 1 year ago
Other use case might be to e.g. subscribe to the domain events when starting container, something similar to https://www.baeldung.com/guice#2-eager-singleton. I guess it might be achieved by using that traversal method within some inherited Container implementation that creates all resources of custom type like EagerSingleton()
:
class EagerSingleton(Singleton):
pass
class MyContainer(Container):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for resource in self.traverse(types=[EagerSingleton]):
resource()
didn't test it so it's more like a pseudo-code but might be useful for someone. In my projects I always have single function to create container instance so I can easily do something similar iniside of that function but this solution ^^ is more general.
EDIT:
I tried to implement this but failed since DeclarativeContainer have custom metaclass that creates Container cls and even if I was able to override __init__()
I didn't have an access to self.providers
and self.traverse
didn't work. And even if I will be able to make it work I still have a problem (this issue) that my EagerSingletons are async and I need to await on them to setup them. I ended up with code like:
from inspect import isawaitable
from dependency_injector.containers import Container
from dependency_injector.providers import Singleton
class EagerSingleton(Singleton):
pass
async def load_eager_singletons(container: Container):
for resource in container.traverse(types=[EagerSingleton]):
singleton = resource()
if isawaitable(singleton):
await singleton
And then in the container:
class Container(containers.DeclarativeContainer):
foo_service = EagerSingleton(
FooService,
dep1=dep1,
dep2=dep2,
...
)
@asynccontextmanager
async def init_container(container: Container):
logger.info("Initiating container")
await load_eager_singletons(container)
try:
yield container
finally:
shutdown_fut = container.shutdown_resources()
if isawaitable(shutdown_fut):
await shutdown_fut
logger.info("Container shutdown")
Im curious if there is a reason that "lazily" loading dependencies is the only way to load any kind of provider (with the exception of
Resources
)I think it makes sense to fail fast with regards to dependencies. For example: If there is a connection issue in a dependency that makes a web request on creation, i'd rather my app fail immediately than
N
amount of time later when that dependency is used.Im writing this issue to see if other folks have written workarounds to eagerly initialize all of a projects dependency at Container creation time. Or maybe there is a good reason to avoid this. Its certainly standard to eagerly load dependencies in Java Spring.
There is a traversal method that is available that could make the manual way doing this a little easier.