mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-06-11 20:11:47 +00:00
Add ignore_count to deferredutil
This commit is contained in:
parent
1c9a3b4b01
commit
5186e68f6b
@ -5,6 +5,7 @@ from foolscap.api import eventually, fireEventually
|
|||||||
from twisted.internet import defer, reactor
|
from twisted.internet import defer, reactor
|
||||||
|
|
||||||
from allmydata.util import log
|
from allmydata.util import log
|
||||||
|
from allmydata.util.assertutil import _assert
|
||||||
from allmydata.util.pollmixin import PollMixin
|
from allmydata.util.pollmixin import PollMixin
|
||||||
|
|
||||||
|
|
||||||
@ -77,28 +78,35 @@ class HookMixin:
|
|||||||
I am a helper mixin that maintains a collection of named hooks, primarily
|
I am a helper mixin that maintains a collection of named hooks, primarily
|
||||||
for use in tests. Each hook is set to an unfired Deferred using 'set_hook',
|
for use in tests. Each hook is set to an unfired Deferred using 'set_hook',
|
||||||
and can then be fired exactly once at the appropriate time by '_call_hook'.
|
and can then be fired exactly once at the appropriate time by '_call_hook'.
|
||||||
|
If 'ignore_count' is given, that number of calls to '_call_hook' will be
|
||||||
|
ignored before firing the hook.
|
||||||
|
|
||||||
I assume a '_hooks' attribute that should set by the class constructor to
|
I assume a '_hooks' attribute that should set by the class constructor to
|
||||||
a dict mapping each valid hook name to None.
|
a dict mapping each valid hook name to None.
|
||||||
"""
|
"""
|
||||||
def set_hook(self, name, d=None):
|
def set_hook(self, name, d=None, ignore_count=0):
|
||||||
"""
|
"""
|
||||||
Called by the hook observer (e.g. by a test).
|
Called by the hook observer (e.g. by a test).
|
||||||
If d is not given, an unfired Deferred is created and returned.
|
If d is not given, an unfired Deferred is created and returned.
|
||||||
The hook must not already be set.
|
The hook must not already be set.
|
||||||
"""
|
"""
|
||||||
|
self._log("set_hook %r, ignore_count=%r" % (name, ignore_count))
|
||||||
if d is None:
|
if d is None:
|
||||||
d = defer.Deferred()
|
d = defer.Deferred()
|
||||||
assert self._hooks[name] is None, self._hooks[name]
|
_assert(ignore_count >= 0, ignore_count=ignore_count)
|
||||||
assert isinstance(d, defer.Deferred), d
|
_assert(name in self._hooks, name=name)
|
||||||
self._hooks[name] = d
|
_assert(self._hooks[name] is None, name=name, hook=self._hooks[name])
|
||||||
|
_assert(isinstance(d, defer.Deferred), d=d)
|
||||||
|
|
||||||
|
self._hooks[name] = (d, ignore_count)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _call_hook(self, res, name):
|
def _call_hook(self, res, name, async=False):
|
||||||
"""
|
"""
|
||||||
Called to trigger the hook, with argument 'res'. This is a no-op if the
|
Called to trigger the hook, with argument 'res'. This is a no-op if
|
||||||
hook is unset. Otherwise, the hook will be unset, and then its Deferred
|
the hook is unset. If the hook's ignore_count is positive, it will be
|
||||||
will be fired synchronously.
|
decremented; if it was already zero, the hook will be unset, and then
|
||||||
|
its Deferred will be fired synchronously.
|
||||||
|
|
||||||
The expected usage is "deferred.addBoth(self._call_hook, 'hookname')".
|
The expected usage is "deferred.addBoth(self._call_hook, 'hookname')".
|
||||||
This ensures that if 'res' is a failure, the hook will be errbacked,
|
This ensures that if 'res' is a failure, the hook will be errbacked,
|
||||||
@ -106,13 +114,25 @@ class HookMixin:
|
|||||||
'res' is returned so that the current result or failure will be passed
|
'res' is returned so that the current result or failure will be passed
|
||||||
through.
|
through.
|
||||||
"""
|
"""
|
||||||
d = self._hooks[name]
|
hook = self._hooks[name]
|
||||||
if d is None:
|
if hook is None:
|
||||||
return defer.succeed(None)
|
return res # pass on error/result
|
||||||
self._hooks[name] = None
|
|
||||||
_with_log(d.callback, res)
|
(d, ignore_count) = hook
|
||||||
|
self._log("call_hook %r, ignore_count=%r" % (name, ignore_count))
|
||||||
|
if ignore_count > 0:
|
||||||
|
self._hooks[name] = (d, ignore_count - 1)
|
||||||
|
else:
|
||||||
|
self._hooks[name] = None
|
||||||
|
if async:
|
||||||
|
_with_log(eventually_callback(d), res)
|
||||||
|
else:
|
||||||
|
_with_log(d.callback, res)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def _log(self, msg):
|
||||||
|
log.msg(msg, level=log.NOISY)
|
||||||
|
|
||||||
|
|
||||||
def async_iterate(process, iterable, *extra_args, **kwargs):
|
def async_iterate(process, iterable, *extra_args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user