def execute(self, *args, **kwargs): """ See :py:func:`silverberg.client.CQLClient.execute` """ d = self._client.execute(*args, **kwargs) timeout_deferred(d, self._timeout, self._reactor, 'CQL query') return d
def health_check(self): """ Synthesizes all health checks and returns a JSON blob containing the key ``healthy``, which is whether all the health checks are healthy, and one key and value per health check. """ # splitting off keys and values here because we want the keys # correlated with the results of the DeferredList at the end # (if self.checks changes in the interim, the DeferredList may not # match up with self.checks.keys() later) keys, checks = ([], []) for k, v in self.checks.iteritems(): keys.append(k) d = maybeDeferred(v) timeout_deferred(d, 15, self.clock, '{} health check'.format(k)) d.addErrback( lambda f: (False, {'reason': f.getTraceback()})) checks.append(d) d = gatherResults(checks) def assembleResults(results): results = [{'healthy': r[0], 'details': r[1]} for r in results] healthy = all(r['healthy'] for r in results) summary = dict(zip(keys, results)) summary['healthy'] = healthy return summary return d.addCallback(assembleResults)
def test_deferred_description_passed_to_TimedOutError(self): """ If a deferred_description is passed, the TimedOutError will have that string as part of it's string representation. """ timeout_deferred(self.deferred, 5.3, self.clock, deferred_description="It'sa ME!") self.clock.advance(6) f = self.failureResultOf(self.deferred, TimedOutError) self.assertIn("It'sa ME! timed out after 5.3 seconds", str(f))
def test_preserves_cancellation_function_callback(self): """ If a cancellation function that callbacks is provided to the deferred being cancelled, its effects will not be overriden with a TimedOutError. """ d = Deferred(lambda c: c.callback('I was cancelled!')) timeout_deferred(d, 10, self.clock) self.assertNoResult(d) self.clock.advance(15) self.assertEqual(self.successResultOf(d), 'I was cancelled!')
def test_preserves_early_cancellation_error(self): """ If the Deferred is manually cancelled before the timeout, it is not re-cancelled (no AlreadyCancelledError), and the CancelledError is not obscured """ timeout_deferred(self.deferred, 10, self.clock) self.assertNoResult(self.deferred) self.deferred.cancel() self.failureResultOf(self.deferred, CancelledError) self.clock.advance(15)
def test_preserves_cancellation_function_errback(self): """ If a cancellation function that errbacks (with a non-CancelledError) is provided to the deferred being cancelled, this other error will not be converted to a TimedOutError. """ d = Deferred(lambda c: c.errback(DummyException('what!'))) timeout_deferred(d, 10, self.clock) self.assertNoResult(d) self.clock.advance(15) self.failureResultOf(d, DummyException)
def test_times_out_if_past_timeout(self): """ The deferred errbacks with a TimedOutError if the timeout occurs before it either callbacks or errbacks. """ clock = Clock() d = Deferred() timeout_deferred(d, 10, clock) self.assertNoResult(d) clock.advance(15) self.failureResultOf(d, TimedOutError)
def wrapper(url, **kwargs): clock = kwargs.pop('clock', self.clock) log = kwargs.pop('log', self.log) method = kwargs.get('method', treq_call.__name__) kwargs.setdefault('headers', {}) if kwargs['headers'] is None: kwargs['headers'] = {} treq_transaction = str(uuid4()) kwargs['headers']['x-otter-request-id'] = [treq_transaction] log = log.bind(system='treq.request', url=url, method=method, url_params=kwargs.get('params'), treq_request_id=treq_transaction) start_time = clock.seconds() log.msg("Request to {method} {url} starting.") d = treq_call(url=url, **kwargs) timeout_deferred(d, 45, clock) def log_request(response): kwargs = {'request_time': clock.seconds() - start_time, 'status_code': response.code, 'headers': response.headers} message = ( "Request to {method} {url} resulted in a {status_code} " "response after {request_time} seconds.") if self.log_response: return ( treq.content(response) .addCallback( lambda b: log.msg(message, response_body=b, **kwargs)) .addCallback(lambda _: response)) log.msg(message, **kwargs) return response def log_failure(failure): request_time = clock.seconds() - start_time log.msg("Request to {method} {url} failed after " "{request_time} seconds.", reason=failure, request_time=request_time) return failure return d.addCallbacks(log_request, log_failure)
def test_propagates_failure_if_failed_before_timeout(self): """ The deferred errbacks with the failure if it fails before the timeout (e.g. timing out the deferred does not obscure the errback failure). """ clock = Clock() d = Deferred() timeout_deferred(d, 10, clock) d.errback(DummyException("fail")) self.failureResultOf(d, DummyException) # the timeout never happens - no further errback occurs clock.advance(15) self.assertIsNone(self.successResultOf(d))
def test_propagates_result_if_success_before_timeout(self): """ The deferred callbacks with the result if it succeeds before the timeout (e.g. timing out the deferred does not obscure the callback value). """ clock = Clock() d = Deferred() timeout_deferred(d, 10, clock) d.callback("Result") self.assertEqual(self.successResultOf(d), "Result") # the timeout never happens - no errback occurs clock.advance(15) self.assertIsNone(self.successResultOf(d))
def _log_request(treq_call, url, **kwargs): """ Log a treq request, including the time it took and the status code. :param callable f: a ``treq`` request method, such as ``treq.request``, or ``treq.get``, ``treq.post``, etc. """ clock = kwargs.pop('clock', reactor) log = kwargs.pop('log', default_log) method = kwargs.get('method', treq_call.__name__) treq_transaction = str(uuid4()) log = log.bind(system='treq.request', url=url, method=method, treq_request_id=treq_transaction) start_time = clock.seconds() log.msg("Request to {method} {url} starting.") d = treq_call(url=url, **kwargs) timeout_deferred(d, 45, clock) def log_request(response): request_time = clock.seconds() - start_time log.msg( ("Request to {method} {url} resulted in a {status_code} response " "after {request_time} seconds."), status_code=response.code, headers=response.headers, request_time=request_time) return response def log_failure(failure): request_time = clock.seconds() - start_time log.msg("Request to {method} {url} failed after {request_time} seconds.", reason=failure, request_time=request_time) return failure return d.addCallbacks(log_request, log_failure)