✨ Add lifespan dependency scope#12529
Conversation
…ure/lifespan-scoped-dependencies
…ed to the deprecated startup and shutdown events. Fixed bugs related to dependency duplcatation within the same router scope. Made more specific dependency related exceptions. Fixed some linting and mypy related issues.
…ure/lifespan-scoped-dependencies
…e with older python versions
…imateLobster/fastapi into feature/lifespan-scoped-dependencies
…ests which check websocket-scoped teardowns before the teardown actually happened on the server side.
…imateLobster/fastapi into feature/lifespan-scoped-dependencies
|
You can just create client instance, and then pass it to application endpoints using app = FastAPI()
client = ...
app.dependency_overrides[MongoClient] = lambda: client |
There are a few problems with this approach which this feature should be able to address:
Further discussion on the subject exists here. |
…imateLobster/fastapi into feature/lifespan-scoped-dependencies
|
📝 Docs preview for commit c7d4d10 at: https://29bab50f.fastapitiangolo.pages.dev Modified Pages |
|
This pull request has a merge conflict that needs to be resolved. |
|
This pull request has a merge conflict that needs to be resolved. |
…imateLobster/fastapi into feature/lifespan-scoped-dependencies
…ompatibility anyways.
dependency_scope arguments to Depends in order to support lifespan scoped dependencies.lifespan dependency scope
|
Updated the PR so it uses the new |
|
This pull request has a merge conflict that needs to be resolved. |
There was a problem hiding this comment.
@UltimateLobster, thank you for work you've done! Looks like you've put a lot of efforts into it!
This feature requires quite a lot of changes. So, let's first wait for Sebastian to validate the general idea.
| ## The `use_cache` argument | ||
|
|
||
| The `use_cache` argument works similarly to the way it worked with endpoint | ||
| scoped dependencies. Meaning, as **FastAPI** gathers lifespan scoped dependencies, it | ||
| will cache dependencies it already encountered before. However, you can disable | ||
| this behavior by passing `use_cache=False` to `Depends`. This will cause a new lifespan | ||
| dependency to be created for every endpoint/dependency/router where it shows up: |
There was a problem hiding this comment.
I think this is not correct. For other dependency scopes, use_cache works for this request only. Here, use_cache has different meaning.
I think for this reason new parameter should be introduced instead of use_cache. And passing use_cache should raise warning as it's useless.
Actually, I'm not sure it's needed.
Do you have any particular use cases for this option?
There was a problem hiding this comment.
I guess I meant to say it works the same way for the respective scope. The relationship between the request dependencies and the request cache, is the same as between lifespan dependencies and lifespan cache. I should've found a better way to explain this.
As for its usefulness, I imagined a case of someone wanting a dedicated evaluation of the dependency. The example I gave in the documentation was a dedicated connection that was only used for requests of a certain route (which would usually require to create a new dependency function for that route).
But I agree it might be somewhat of a weak reason to support use_cache=False (along with wanting to allow a behavior that a reader of Depends's signature might expect).
If you think it would be better to disallow use_cache=False until a better argument arises, I won't mind doing it .
lifespan dependency scopelifespan dependency scope
Thanks for taking a look at this! |
Support for lifespan scoped dependencies
This feature adds a scope to
Depends:"lifespan".If it is
"lifespan"the dependency will be evaluated at the application startup (the value will be reused in all endpoints), and will be teared down at the application shutdown. It will be useful when defining db connections which need to be maintained and reused throughout the application's up-time:The
use_cacheargument works in the same way for dependencies with"lifespan"scope as it is for dependencies with"request"or"function"scope:Implementation details to note:
lifespanargument, it will be merged with the internal lifespan using the recently added_merge_lifespan_contextutilitylifespanargument (if a lifespan is supplied, the events will never be handled). Since this PR makes it so we always have alifespanarugment passed, it would've meant theon_event,on_startupandon_shutdownfeatures would break. I solved it by manually calling them in the application's internal lifespan.get_flat_dependentto concat dependencies as well.Things left to do:There are still tests missing from this PR which I'm still working on (Specifically, I need to add tests to cover interactions with websockets, as well as interactions with dependency overrides).I still need to add the necessary documentation and examples.