-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
PeriodicCallback: support async/coroutine callback #2924
Conversation
4fd0ead
to
641f589
Compare
641f589
to
673f8cd
Compare
rebased on master, latest CI matrix ran |
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 couple of type annotation issues here. I thought we had enough type inferencing enabled in tests to catch this but I guess not. Adding a -> None
to the test_
methods might enable this.
91e96e2
to
74c78d2
Compare
btw, on macOS I get one more unrelated mypy warning:
and it makes sense why it does not trigger in linux or windows modes:
|
…lback to accept coroutines
e806eb5
to
30af70b
Compare
rebased |
tornado/ioloop.py
Outdated
self, when: float, callback: Callable[..., None], *args: Any, **kwargs: Any | ||
self, | ||
when: float, | ||
callback: Callable[..., Optional[Awaitable]], |
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.
call_at
and call_later
should have the same type signature. And I think that since they don't do anything with the return value of their argument, they should actually follow the example of add_callback
and take an unspecialized Callable
. (or equivalently, Callable[..., Any]
, which is what asyncio uses)
tornado/ioloop.py
Outdated
@@ -863,11 +868,14 @@ class PeriodicCallback(object): | |||
|
|||
.. versionchanged:: 5.1 | |||
The ``jitter`` argument is added. | |||
|
|||
.. versionchanged:: 6.2 | |||
The ``callback`` argument may be a coroutine. |
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.
The change is more subtle than that: This PR adds support for native coroutines. Decorated coroutines have always been supported by the code (I think; haven't tested it. The mypy annotations would reject them but I'm pretty sure they'd still work). However, this changes their semantics: they were previously fire-and-forget (so a slow coroutine could end up with multiple copies of the task running concurrently) while now they affect scheduling (so a slow coroutine will reduce the number of calls made per unit of time).
This is a potentially breaking change so we don't want to make it by accident. I think it's probably the right move but it needs to be a deliberate decision and documented accordingly.
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.
Native coroutines worked too, I used them for a long time, but they were fire-and-forget as you say. I'll update this to be more specific.
@@ -694,6 +694,60 @@ def test_timedelta(self): | |||
self.assertEqual(pc.callback_time, expected_callback_time) | |||
|
|||
|
|||
class TestPeriodicCallbackAsync(AsyncTestCase): |
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.
I think we want tests that cover the overrun behavior (since this is the part that's changing for decorated coroutines between this change and the prior implementation)
coroutine or plain, returning any type
Thanks! |
clean-up some methods that were missed in tornadoweb#2924
clean-up some methods that were missed in tornadoweb#2924
ISSUE: tornadoweb#2828 * ioloop: call_later() and call_at() take any Callable coroutine or plain, returning any type Co-authored-by: agnewee <agnewee@gmail.com>
#2832 plus some tests
EDIT: nevermind, figured out how to avoid this
ORIGINAL:
I can't quite figure out how to quiet this error log:
The usual pattern doesn't work:
even if I extend it to: