Introduce IOLoop.spawn_callback.
This makes it easier and more discoverable to run a callback without stack_context. Closes #867.
This commit is contained in:
parent
a0fe934435
commit
4e9de2e43f
|
@ -486,6 +486,19 @@ class IOLoop(Configurable):
|
|||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def spawn_callback(self, callback, *args, **kwargs):
|
||||
"""Calls the given callback on the next IOLoop iteration.
|
||||
|
||||
Unlike all other callback-related methods on IOLoop,
|
||||
``spawn_callback`` does not associate the callback with its caller's
|
||||
``stack_context``, so it is suitable for fire-and-forget callbacks
|
||||
that should not interfere with the caller.
|
||||
|
||||
.. versionadded:: 4.0
|
||||
"""
|
||||
with stack_context.NullContext():
|
||||
self.add_callback(callback, *args, **kwargs)
|
||||
|
||||
def add_future(self, future, callback):
|
||||
"""Schedules a callback on the ``IOLoop`` when the given
|
||||
`.Future` is finished.
|
||||
|
|
|
@ -273,6 +273,19 @@ class TestIOLoop(AsyncTestCase):
|
|||
with ExpectLog(app_log, "Exception in callback"):
|
||||
self.wait()
|
||||
|
||||
def test_spawn_callback(self):
|
||||
# An added callback runs in the test's stack_context, so will be
|
||||
# re-arised in wait().
|
||||
self.io_loop.add_callback(lambda: 1/0)
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
self.wait()
|
||||
# A spawned callback is run directly on the IOLoop, so it will be
|
||||
# logged without stopping the test.
|
||||
self.io_loop.spawn_callback(lambda: 1/0)
|
||||
self.io_loop.add_callback(self.stop)
|
||||
with ExpectLog(app_log, "Exception in callback"):
|
||||
self.wait()
|
||||
|
||||
|
||||
# Deliberately not a subclass of AsyncTestCase so the IOLoop isn't
|
||||
# automatically set as current.
|
||||
|
|
Loading…
Reference in New Issue