-
Notifications
You must be signed in to change notification settings - Fork 404
Remove sentinel logcontext in Clock utilities (looping_call, looping_call_now, call_later)
#18907
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
Changes from 9 commits
6170762
5d2e4c4
414b178
788cd19
77b3228
91f7bb3
2e88eb3
fbf5946
3809f3f
442dbc0
13b938f
04825eb
f4ad07d
a8e66e7
0780183
c535d8a
aec7065
2aa15b0
1c001c9
13a5a36
eae83e8
3797515
9116e74
57cc675
45e6b78
4145160
f2ae33a
160eb63
c8d0f97
774d25f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,6 +121,8 @@ class Clock: | |
|
|
||
| async def sleep(self, seconds: float) -> None: | ||
| d: defer.Deferred[float] = defer.Deferred() | ||
| # Start task in the `sentinel` logcontext, to avoid leaking the current context | ||
| # into the reactor once it finishes. | ||
| with context.PreserveLoggingContext(): | ||
| self._reactor.callLater(seconds, d.callback, seconds) | ||
| await d | ||
|
|
@@ -149,8 +151,9 @@ def looping_call( | |
| this functionality thanks to this function being a thin wrapper around | ||
| `twisted.internet.task.LoopingCall`. | ||
|
|
||
| Note that the function will be called with no logcontext, so if it is anything | ||
| other than trivial, you probably want to wrap it in run_as_background_process. | ||
| Note that the function will be called with generic `looping_call` logcontext, so | ||
| if it is anything other than a trivial task, you probably want to wrap it in | ||
| `run_as_background_process` to give it more specific label and track metrics. | ||
|
|
||
| Args: | ||
| f: The function to call repeatedly. | ||
|
|
@@ -172,8 +175,9 @@ def looping_call_now( | |
| As with `looping_call`: subsequent calls are not scheduled until after the | ||
| the Awaitable returned by a previous call has finished. | ||
|
|
||
| Also as with `looping_call`: the function is called with no logcontext and | ||
| you probably want to wrap it in `run_as_background_process`. | ||
| Note that the function will be called with generic `looping_call` logcontext, so | ||
| if it is anything other than a trivial task, you probably want to wrap it in | ||
| `run_as_background_process` to give it more specific label and track metrics. | ||
|
|
||
| Args: | ||
| f: The function to call repeatedly. | ||
|
|
@@ -192,19 +196,37 @@ def _looping_call_common( | |
| **kwargs: P.kwargs, | ||
| ) -> LoopingCall: | ||
| """Common functionality for `looping_call` and `looping_call_now`""" | ||
| call = task.LoopingCall(f, *args, **kwargs) | ||
| call.clock = self._reactor | ||
| d = call.start(msec / 1000.0, now=now) | ||
| d.addErrback(log_failure, "Looping call died", consumeErrors=False) | ||
| return call | ||
|
|
||
| def wrapped_f(*args: P.args, **kwargs: P.kwargs) -> object: | ||
| # Because this is a callback from the reactor, we will be using the | ||
| # `sentinel` log context at this point. We want to log with some logcontext | ||
| # as we want to know which server the logs came from. | ||
| # | ||
| # This also ensures that we return to the `sentinel` context when we exit | ||
| # this function and yield control back to the reactor to avoid leaking the | ||
| # current logcontext to the reactor (which would then get picked up and | ||
| # associated with the next thing the reactor does) | ||
| with context.LoggingContext("looping_call"): | ||
| return f(*args, **kwargs) | ||
|
|
||
| # Start task in the `sentinel` logcontext, to avoid leaking the current context | ||
| # into the reactor if `d` ever finishes (perhaps someone cancels the looping | ||
| # call) | ||
| with context.PreserveLoggingContext(): | ||
MadLittleMods marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| call = task.LoopingCall(wrapped_f, *args, **kwargs) | ||
| call.clock = self._reactor | ||
| d = call.start(msec / 1000.0, now=now) | ||
| d.addErrback(log_failure, "Looping call died", consumeErrors=False) | ||
| return call | ||
|
|
||
| def call_later( | ||
| self, delay: float, callback: Callable, *args: Any, **kwargs: Any | ||
| ) -> IDelayedCall: | ||
| """Call something later | ||
|
|
||
| Note that the function will be called with no logcontext, so if it is anything | ||
| other than trivial, you probably want to wrap it in run_as_background_process. | ||
| Note that the function will be called with generic `looping_call` logcontext, so | ||
| if it is anything other than a trivial task, you probably want to wrap it in | ||
| `run_as_background_process` to give it more specific label and track metrics. | ||
|
|
||
| Args: | ||
| delay: How long to wait in seconds. | ||
|
|
@@ -214,9 +236,19 @@ def call_later( | |
| """ | ||
|
|
||
| def wrapped_callback(*args: Any, **kwargs: Any) -> None: | ||
| with context.PreserveLoggingContext(): | ||
| # Because this is a callback from the reactor, we will be using the | ||
| # `sentinel` log context at this point. We want to log with some logcontext | ||
| # as we want to know which server the logs came from. | ||
| # | ||
| # This also ensures that we return to the `sentinel` context when we exit | ||
| # this function and yield control back to the reactor to avoid leaking the | ||
| # current logcontext to the reactor (which would then get picked up and | ||
| # associated with the next thing the reactor does) | ||
| with context.LoggingContext("call_later"): | ||
| callback(*args, **kwargs) | ||
|
|
||
| # Start task in the `sentinel` logcontext, to avoid leaking the current context | ||
| # into the reactor once it finishes. | ||
| with context.PreserveLoggingContext(): | ||
|
||
| return self._reactor.callLater(delay, wrapped_callback, *args, **kwargs) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not your problem to deal with, but I've often wondered why we don't just make
looping_calltake a name and do this wrapping itself. I can't think of a genericlooping_callctx ever being the desirable outcome.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A possible future 👍