diff options
author | Erik Johnston <erik@matrix.org> | 2018-09-14 19:23:07 +0100 |
---|---|---|
committer | Erik Johnston <erik@matrix.org> | 2018-09-14 19:23:07 +0100 |
commit | fcfe7a850dada2e65982f2bc805d8bc409f07512 (patch) | |
tree | 01c899c308ddae6c7250f45ce9eeb4294f6bfea2 /synapse/util | |
parent | don't filter membership events based on history visibility (#3874) (diff) | |
download | synapse-fcfe7a850dada2e65982f2bc805d8bc409f07512.tar.xz |
Add an awful secondary timeout to fix wedged requests
This is an attempt to mitigate #3842 by adding yet-another-timeout
Diffstat (limited to 'synapse/util')
-rw-r--r-- | synapse/util/async_helpers.py | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/synapse/util/async_helpers.py b/synapse/util/async_helpers.py index 9b3f2f4b96..083e4f4128 100644 --- a/synapse/util/async_helpers.py +++ b/synapse/util/async_helpers.py @@ -438,3 +438,54 @@ def _cancelled_to_timed_out_error(value, timeout): value.trap(CancelledError) raise DeferredTimeoutError(timeout, "Deferred") return value + + +def timeout_no_seriously(deferred, timeout, reactor): + """The in build twisted deferred addTimeout (and the method above) + completely fail to time things out under some unknown circumstances. + + Lets try a different way of timing things out and maybe that will make + things work?! + + TODO: Kill this with fire. + """ + + new_d = defer.Deferred() + + timed_out = [False] + + def time_it_out(): + timed_out[0] = True + deferred.cancel() + + if not new_d.called: + new_d.errback(DeferredTimeoutError(timeout, "Deferred")) + + delayed_call = reactor.callLater(timeout, time_it_out) + + def convert_cancelled(value): + if timed_out[0]: + return _cancelled_to_timed_out_error(value, timeout) + return value + + deferred.addBoth(convert_cancelled) + + def cancel_timeout(result): + # stop the pending call to cancel the deferred if it's been fired + if delayed_call.active(): + delayed_call.cancel() + return result + + deferred.addBoth(cancel_timeout) + + def success_cb(val): + if not new_d.called: + new_d.callback(val) + + def failure_cb(val): + if not new_d.called: + new_d.errback(val) + + deferred.addCallbacks(success_cb, failure_cb) + + return new_d |