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

traverse visits providers in a random order #780

Open
BEllis opened this issue Jan 31, 2024 · 1 comment
Open

traverse visits providers in a random order #780

BEllis opened this issue Jan 31, 2024 · 1 comment

Comments

@BEllis
Copy link

BEllis commented Jan 31, 2024

When container.init_resources() is called, it is expected that resources are loaded in the same order every time (and ideally in a way that can be controlled, but that is outside the scope of this bug).

What actually happens is the resources are initialized in a random order each time an application is started.

This is due to def traverse(...) using set() to iterate over the providers, this results in a random start-up order every time an app is restarted.

Proposed short-term solution is to init providers in the order they are defined in the container.
Proposed long-term solution (separate ticket / feature request) is that providers can be given a "priority" or "order" to indicate precedence.

@BEllis
Copy link
Author

BEllis commented Feb 1, 2024

I've been using this as a work around, I'll look at raising a PR when I get some time.

    def traverse(
        *target_providers: Provider[Any],
        types: Iterable[type] | None = None,
    ) -> Iterator[Provider[Any]]:
        """Return providers traversal generator."""
        visited = set()

        providers_ = [*target_providers]

        if types:
            types_tuple: tuple[type, ...] = tuple[type, ...](types)
        else:
            types_tuple = tuple[type, ...]()

        for provider in providers_:
            if provider in visited:
                continue

            visited.add(provider)

            for child in provider.related:
                if child in visited:
                    continue
                providers_.append(child)

            if types and not isinstance(provider, types_tuple):
                continue

            yield provider

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

1 participant