Skip to content

Conversation

davidism
Copy link
Member

@davidism davidism commented Jul 8, 2022

While investigating ContextVar in pallets/werkzeug#2436, I realized that there's no reason to use a LocalStack now to manage RequestContext and AppContext.

LocalStack incurs some performance and memory overhead on every push and pop because it uses a mutable list as the value of the ContextVar. Since we can never know if this context was copied by asyncio or asgiref into a child context, we always have to copy the list before mutating it, then set it again, otherwise mutations would be unsafe.

RequestContext and AppContext already have their own internal thread-unsafe state to track how many times they've been pushed, and implicit app contexts for request contexts.

Now, the contexts keep an internal stack of contextvars.Token objects, appending a new token when pushed. This allows resetting the context var to the previous value when the context is popped. Essentially, this makes the contexts singly-linked lists instead of stacks.

This does mean that _app_ctx_stack.top and _request_ctx_stack.top will no longer exist. Currently, there is a fake object that keeps the API around, since it's used by extensions to store state. However, importing them or accessing them will show deprecation warnings. Docs now encourage using g instead of the internal contexts for extension state. I added app_ctx and request_ctx objects that are proxies to the current objects, in case existing extensions want a less drastic change.

This bumps the minimum version of Werkzeug to 2.2 (currently 2.2.0a1) to take advantage of changes to its implementation of LocalProxy.

@davidism davidism added this to the 2.2.0 milestone Jul 8, 2022
@davidism davidism merged commit cbebdae into main Jul 8, 2022
@davidism davidism deleted the refactor-context-stack branch July 8, 2022 18:58
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants