1 from __future__ import division
6 from twisted.internet import defer, reactor
7 from twisted.python import failure
11 reactor.callLater(t, d.callback, None)
14 def retry(message, delay):
16 @retry('Error getting block:', 1)
17 @defer.inlineCallbacks
23 @defer.inlineCallbacks
24 def f(*args, **kwargs):
27 result = yield func(*args, **kwargs)
36 defer.returnValue(result)
40 class ReplyMatcher(object):
42 Converts request/got response interface to deferred interface
45 def __init__(self, func, timeout=5):
47 self.timeout = timeout
50 def __call__(self, id):
52 uniq = random.randrange(2**256)
55 df, timer = self.map[id].pop(uniq)
56 df.errback(failure.Failure(defer.TimeoutError()))
59 self.map.setdefault(id, {})[uniq] = (df, reactor.callLater(self.timeout, timeout))
62 def got_response(self, id, resp):
63 if id not in self.map:
65 for df, timer in self.map.pop(id).itervalues():
69 class GenericDeferrer(object):
71 Converts query with identifier/got response interface to deferred interface
74 def __init__(self, max_id, func, timeout=5):
77 self.timeout = timeout
80 def __call__(self, *args, **kwargs):
82 id = random.randrange(self.max_id)
83 if id not in self.map:
88 df.errback(failure.Failure(defer.TimeoutError()))
89 timer = reactor.callLater(self.timeout, timeout)
90 self.func(id, *args, **kwargs)
91 self.map[id] = df, timer
94 def got_response(self, id, resp):
95 if id not in self.map:
97 df, timer = self.map.pop(id)
101 class NotNowError(Exception):
104 class DeferredCacher(object):
106 like memoize, but for functions that return Deferreds
113 @DeferredCacher.with_backing(bsddb.hashopen(...))
120 def with_backing(cls, backing):
121 return lambda func: cls(func, backing)
123 def __init__(self, func, backing=None):
128 self.backing = backing
131 @defer.inlineCallbacks
132 def __call__(self, key):
133 if key in self.waiting:
134 yield self.waiting[key]
136 if key in self.backing:
137 defer.returnValue(self.backing[key])
139 self.waiting[key] = defer.Deferred()
141 value = yield self.func(key)
143 self.waiting.pop(key).callback(None)
145 self.backing[key] = value
146 defer.returnValue(value)
148 def call_now(self, key):
149 if key in self.waiting:
152 if key in self.backing:
153 return self.backing[key]
155 self.waiting[key] = defer.Deferred()
157 self.backing[key] = value
158 self.waiting.pop(key).callback(None)
160 self.waiting.pop(key).callback(None)
161 fail.printTraceback()
162 self.func(key).addCallback(cb).addErrback(eb)