Skip to content

PYTHON-5406 - AsyncPeriodicExecutor must reset CSOT contextvars befor… #2360

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

Merged
merged 5 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pymongo/_asyncio_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def cancelling(self) -> int:
return self._cancel_requests


# We can directly pass an empty Context() object to create_task in Python >= 3.11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we'd want to do that. The user might be have contextvars that they want to propagate to the background tasks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better idea I had was to explicitly remove our CSOT contextvars and leave the rest alone.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then, should we remove this comment?

def create_task(coro: Coroutine[Any, Any, Any], *, name: Optional[str] = None) -> asyncio.Task:
if sys.version_info >= (3, 11):
return asyncio.create_task(coro, name=name)
Expand Down
6 changes: 6 additions & 0 deletions pymongo/_csot.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
DEADLINE: ContextVar[float] = ContextVar("DEADLINE", default=float("inf"))


def reset_all() -> None:
TIMEOUT.set(None)
RTT.set(0.0)
DEADLINE.set(float("inf"))


def get_timeout() -> Optional[float]:
return TIMEOUT.get(None)

Expand Down
3 changes: 3 additions & 0 deletions pymongo/periodic_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import weakref
from typing import Any, Optional

from pymongo import _csot
from pymongo._asyncio_task import create_task
from pymongo.lock import _create_lock

Expand Down Expand Up @@ -93,6 +94,8 @@ def skip_sleep(self) -> None:
self._skip_sleep = True

async def _run(self) -> None:
# The CSOT contextvars must be cleared inside the executor task before execution begins
_csot.reset_all()
while not self._stopped:
if self._task and self._task.cancelling(): # type: ignore[unused-ignore, attr-defined]
raise asyncio.CancelledError
Expand Down
Loading