Fix logcontext leak in HttpTransactionCache

ONE DAY I WILL PURGE THE WORLD OF THIS EVIL
This commit is contained in:
Richard van der Hoff 2018-05-21 16:58:20 +01:00
parent 6d6e7288fe
commit 6e1cb54a05
2 changed files with 38 additions and 21 deletions

View file

@ -19,6 +19,7 @@ import logging
from synapse.api.auth import get_access_token_from_request
from synapse.util.async import ObservableDeferred
from synapse.util.logcontext import make_deferred_yieldable, run_in_background
logger = logging.getLogger(__name__)
@ -80,31 +81,26 @@ class HttpTransactionCache(object):
Returns:
Deferred which resolves to a tuple of (response_code, response_dict).
"""
try:
return self.transactions[txn_key][0].observe()
except (KeyError, IndexError):
pass # execute the function instead.
if txn_key in self.transactions:
observable = self.transactions[txn_key][0]
else:
# execute the function instead.
deferred = run_in_background(fn, *args, **kwargs)
deferred = fn(*args, **kwargs)
observable = ObservableDeferred(deferred)
self.transactions[txn_key] = (observable, self.clock.time_msec())
observable = ObservableDeferred(deferred, consumeErrors=False)
self.transactions[txn_key] = (observable, self.clock.time_msec())
# if the request fails with an exception, remove it
# from the transaction map. This is done to ensure that we don't
# cache transient errors like rate-limiting errors, etc.
def remove_from_map(err):
self.transactions.pop(txn_key, None)
# we deliberately do not propagate the error any further, as we
# expect the observers to have reported it.
# if the request fails with an exception, remove it from the
# transaction map. This is done to ensure that we don't cache
# transient errors like rate-limiting errors, etc.
#
# (make sure we add this errback *after* adding the key above, in case
# the deferred has already failed and is running errbacks
# synchronously)
def remove_from_map(err):
self.transactions.pop(txn_key, None)
# we deliberately do not propagate the error any further, as we
# expect the observers to have reported it.
deferred.addErrback(remove_from_map)
deferred.addErrback(remove_from_map)
return observable.observe()
return make_deferred_yieldable(observable.observe())
def _cleanup(self):
now = self.clock.time_msec()