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

[Discussion] Entering/Existing Scopes? #162

Open
Enforcer opened this issue Oct 17, 2020 · 3 comments
Open

[Discussion] Entering/Existing Scopes? #162

Enforcer opened this issue Oct 17, 2020 · 3 comments

Comments

@Enforcer
Copy link

Hi, let me start from thanking for the awesome project 🎉

Recently I was implementing a custom scope and I noticed a need for explicitly demarking beginning and ending of this scope. Mine was similar to flask_injector's RequestScope but could also be used outside web framework context, i.e. in background jobs or CLI commands.

I know injector is heavily inspired by Guice and I noticed in their documentation that their API supports enter and exit methods.

I'd like to start a brainstorming about this concept to either:

  • introduce a new API for entering/exiting a scope - similar to configure, provide empty enter, exit methods to be overriden,
  • expand documentation to give others tips to implement such a thing on their own,
  • other?

BTW, here's my custom scope implementation: https://github.com/Enforcer/clean-architecture/blob/master/auctioning_platform/main/main/modules.py#L21 Basically, it's a copy-pasted ThreadLocalScope with extras.

@jstasiak
Copy link
Collaborator

Hey, thank you for the kind words, I'm happy you found the project useful. I don't have any specifics in mind at this point but yes, the whole scope entering/exiting concept seems rather useful and desired, I'll give it some thinking.

@signalpillar
Copy link

I think this ticket is a great opportunity to collect knowledge about the cases.

It's needless to say that it's great to have this small and easy to understand library. An easy and pragmatic approach may not be the simplest to maintain in the future.

I was thinking too what that life-cycle of the dependency is. And looks like it's very dependent on the usage context of the dependency. The integration point of the injector with the usage context is the right place to define what the life-cycle is and what to trigger life-cycle methods on the dependencies.

I had one case when I needed to close resources at the end of the request in nameko-injector integration.

The first problem for me was to declare what's the protocol that determines life-cycle of the dependency. I can think about close method. enter is a dependency creation by a provider.

Following interface-segregation principle we probably need many. Closable dependency, timeout-aware dependency etc.

After that we need to create a new scope that understands the protocols and provides API to fan out protocol call on all the dependencies. In my case I decided to not even have such method on the scope as I wanted to decide rules of error handling outside (in middleware)

This library has great documentation that helped me many times. Maybe the first step is to write a new section about custom scopes, life-cycle management in terms of good practices.

@JosXa
Copy link

JosXa commented Dec 5, 2020

Hmm, I'm coming across the same problem right as we speak.. You mentioned middleware, and I think that might indeed be the right layer of abstraction for a generic scope layer, i.e. something that initializes, calls next(), and so on, until the scope is disposed and we follow the chain in reverse:

TContext = TypeVar("TContext")

# These get chained by each exposing a `call_next`
Delegate = Callable[[TContext, "Delegate"], Union[Any, Awaitable[Any]]]

Maybe it's overthinking it, but you do have a point that there's a ton of cases to consider and this would be the most general approach.

Check out https://github.com/robdmc/consecution/tree/master

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

4 participants