mirror of
				https://github.com/element-hq/synapse.git
				synced 2025-10-31 00:02:00 -04:00 
			
		
		
		
	Backport deferred.addTimeout
Twisted 16.0 doesn't have addTimeout, so let's backport it.
This commit is contained in:
		
							parent
							
								
									1ea904b9f0
								
							
						
					
					
						commit
						9d2c1b8429
					
				| @ -28,7 +28,7 @@ class RequestTimedOutError(SynapseError): | |||||||
| def cancelled_to_request_timed_out_error(value): | def cancelled_to_request_timed_out_error(value): | ||||||
|     """Turns CancelledErrors into RequestTimedOutErrors. |     """Turns CancelledErrors into RequestTimedOutErrors. | ||||||
| 
 | 
 | ||||||
|     For use with deferred.addTimeout() |     For use with async.add_timeout_to_deferred | ||||||
|     """ |     """ | ||||||
|     if isinstance(value, failure.Failure): |     if isinstance(value, failure.Failure): | ||||||
|         value.trap(CancelledError) |         value.trap(CancelledError) | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ from synapse.api.errors import ( | |||||||
|     CodeMessageException, MatrixCodeMessageException, SynapseError, Codes, |     CodeMessageException, MatrixCodeMessageException, SynapseError, Codes, | ||||||
| ) | ) | ||||||
| from synapse.http import cancelled_to_request_timed_out_error | from synapse.http import cancelled_to_request_timed_out_error | ||||||
|  | from synapse.util.async import add_timeout_to_deferred | ||||||
| from synapse.util.caches import CACHE_SIZE_FACTOR | from synapse.util.caches import CACHE_SIZE_FACTOR | ||||||
| from synapse.util.logcontext import make_deferred_yieldable | from synapse.util.logcontext import make_deferred_yieldable | ||||||
| import synapse.metrics | import synapse.metrics | ||||||
| @ -102,8 +103,9 @@ class SimpleHttpClient(object): | |||||||
|             request_deferred = self.agent.request( |             request_deferred = self.agent.request( | ||||||
|                 method, uri, *args, **kwargs |                 method, uri, *args, **kwargs | ||||||
|             ) |             ) | ||||||
|             request_deferred.addTimeout( |             add_timeout_to_deferred( | ||||||
|                 60, reactor, cancelled_to_request_timed_out_error, |                 request_deferred, | ||||||
|  |                 60, cancelled_to_request_timed_out_error, | ||||||
|             ) |             ) | ||||||
|             response = yield make_deferred_yieldable(request_deferred) |             response = yield make_deferred_yieldable(request_deferred) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ from twisted.web._newclient import ResponseDone | |||||||
| from synapse.http import cancelled_to_request_timed_out_error | from synapse.http import cancelled_to_request_timed_out_error | ||||||
| from synapse.http.endpoint import matrix_federation_endpoint | from synapse.http.endpoint import matrix_federation_endpoint | ||||||
| import synapse.metrics | import synapse.metrics | ||||||
| from synapse.util.async import sleep | from synapse.util.async import sleep, add_timeout_to_deferred | ||||||
| from synapse.util import logcontext | from synapse.util import logcontext | ||||||
| from synapse.util.logcontext import make_deferred_yieldable | from synapse.util.logcontext import make_deferred_yieldable | ||||||
| import synapse.util.retryutils | import synapse.util.retryutils | ||||||
| @ -193,9 +193,10 @@ class MatrixFederationHttpClient(object): | |||||||
|                             Headers(headers_dict), |                             Headers(headers_dict), | ||||||
|                             producer |                             producer | ||||||
|                         ) |                         ) | ||||||
|                         request_deferred.addTimeout( |                         add_timeout_to_deferred( | ||||||
|  |                             request_deferred, | ||||||
|                             timeout / 1000. if timeout else 60, |                             timeout / 1000. if timeout else 60, | ||||||
|                             reactor, cancelled_to_request_timed_out_error, |                             cancelled_to_request_timed_out_error, | ||||||
|                         ) |                         ) | ||||||
|                         response = yield make_deferred_yieldable( |                         response = yield make_deferred_yieldable( | ||||||
|                             request_deferred, |                             request_deferred, | ||||||
|  | |||||||
| @ -13,15 +13,17 @@ | |||||||
| # See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and | ||||||
| # limitations under the License. | # limitations under the License. | ||||||
| 
 | 
 | ||||||
| from twisted.internet import defer, reactor | from twisted.internet import defer | ||||||
| from twisted.internet.defer import TimeoutError |  | ||||||
| 
 | 
 | ||||||
| from synapse.api.constants import EventTypes, Membership | from synapse.api.constants import EventTypes, Membership | ||||||
| from synapse.api.errors import AuthError | from synapse.api.errors import AuthError | ||||||
| from synapse.handlers.presence import format_user_presence_state | from synapse.handlers.presence import format_user_presence_state | ||||||
| 
 | 
 | ||||||
| from synapse.util.logutils import log_function | from synapse.util.logutils import log_function | ||||||
| from synapse.util.async import ObservableDeferred | from synapse.util.async import ( | ||||||
|  |     ObservableDeferred, add_timeout_to_deferred, | ||||||
|  |     DeferredTimeoutError, | ||||||
|  | ) | ||||||
| from synapse.util.logcontext import PreserveLoggingContext, preserve_fn | from synapse.util.logcontext import PreserveLoggingContext, preserve_fn | ||||||
| from synapse.util.metrics import Measure | from synapse.util.metrics import Measure | ||||||
| from synapse.types import StreamToken | from synapse.types import StreamToken | ||||||
| @ -332,8 +334,9 @@ class Notifier(object): | |||||||
|                     # Now we wait for the _NotifierUserStream to be told there |                     # Now we wait for the _NotifierUserStream to be told there | ||||||
|                     # is a new token. |                     # is a new token. | ||||||
|                     listener = user_stream.new_listener(prev_token) |                     listener = user_stream.new_listener(prev_token) | ||||||
|                     listener.deferred.addTimeout( |                     add_timeout_to_deferred( | ||||||
|                         (end_time - now) / 1000., reactor, |                         listener.deferred, | ||||||
|  |                         (end_time - now) / 1000., | ||||||
|                     ) |                     ) | ||||||
|                     with PreserveLoggingContext(): |                     with PreserveLoggingContext(): | ||||||
|                         yield listener.deferred |                         yield listener.deferred | ||||||
| @ -347,7 +350,7 @@ class Notifier(object): | |||||||
|                     # Update the prev_token to the current_token since nothing |                     # Update the prev_token to the current_token since nothing | ||||||
|                     # has happened between the old prev_token and the current_token |                     # has happened between the old prev_token and the current_token | ||||||
|                     prev_token = current_token |                     prev_token = current_token | ||||||
|                 except TimeoutError: |                 except DeferredTimeoutError: | ||||||
|                     break |                     break | ||||||
|                 except defer.CancelledError: |                 except defer.CancelledError: | ||||||
|                     break |                     break | ||||||
| @ -552,11 +555,14 @@ class Notifier(object): | |||||||
|             if end_time <= now: |             if end_time <= now: | ||||||
|                 break |                 break | ||||||
| 
 | 
 | ||||||
|             listener.deferred.addTimeout((end_time - now) / 1000., reactor) |             add_timeout_to_deferred( | ||||||
|  |                 listener.deferred.addTimeout, | ||||||
|  |                 (end_time - now) / 1000., | ||||||
|  |             ) | ||||||
|             try: |             try: | ||||||
|                 with PreserveLoggingContext(): |                 with PreserveLoggingContext(): | ||||||
|                     yield listener.deferred |                     yield listener.deferred | ||||||
|             except TimeoutError: |             except DeferredTimeoutError: | ||||||
|                 break |                 break | ||||||
|             except defer.CancelledError: |             except defer.CancelledError: | ||||||
|                 break |                 break | ||||||
|  | |||||||
| @ -15,6 +15,8 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from twisted.internet import defer, reactor | from twisted.internet import defer, reactor | ||||||
|  | from twisted.internet.defer import CancelledError | ||||||
|  | from twisted.python import failure | ||||||
| 
 | 
 | ||||||
| from .logcontext import ( | from .logcontext import ( | ||||||
|     PreserveLoggingContext, make_deferred_yieldable, preserve_fn |     PreserveLoggingContext, make_deferred_yieldable, preserve_fn | ||||||
| @ -392,3 +394,68 @@ class ReadWriteLock(object): | |||||||
|                     self.key_to_current_writer.pop(key) |                     self.key_to_current_writer.pop(key) | ||||||
| 
 | 
 | ||||||
|         defer.returnValue(_ctx_manager()) |         defer.returnValue(_ctx_manager()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class DeferredTimeoutError(Exception): | ||||||
|  |     """ | ||||||
|  |     This error is raised by default when a L{Deferred} times out. | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def add_timeout_to_deferred(deferred, timeout, on_timeout_cancel=None): | ||||||
|  |     """ | ||||||
|  |     Add a timeout to a deferred by scheduling it to be cancelled after | ||||||
|  |     timeout seconds. | ||||||
|  | 
 | ||||||
|  |     This is essentially a backport of deferred.addTimeout, which was introduced | ||||||
|  |     in twisted 16.5. | ||||||
|  | 
 | ||||||
|  |     If the deferred gets timed out, it errbacks with a DeferredTimeoutError, | ||||||
|  |     unless a cancelable function was passed to its initialization or unless | ||||||
|  |     a different on_timeout_cancel callable is provided. | ||||||
|  | 
 | ||||||
|  |     Args: | ||||||
|  |         deferred (defer.Deferred): deferred to be timed out | ||||||
|  |         timeout (Number): seconds to time out after | ||||||
|  | 
 | ||||||
|  |         on_timeout_cancel (callable): A callable which is called immediately | ||||||
|  |             after the deferred times out, and not if this deferred is | ||||||
|  |             otherwise cancelled before the timeout. | ||||||
|  | 
 | ||||||
|  |             It takes an arbitrary value, which is the value of the deferred at | ||||||
|  |             that exact point in time (probably a CancelledError Failure), and | ||||||
|  |             the timeout. | ||||||
|  | 
 | ||||||
|  |             The default callable (if none is provided) will translate a | ||||||
|  |             CancelledError Failure into a DeferredTimeoutError. | ||||||
|  |     """ | ||||||
|  |     timed_out = [False] | ||||||
|  | 
 | ||||||
|  |     def time_it_out(): | ||||||
|  |         timed_out[0] = True | ||||||
|  |         deferred.cancel() | ||||||
|  | 
 | ||||||
|  |     delayed_call = reactor.callLater(timeout, time_it_out) | ||||||
|  | 
 | ||||||
|  |     def convert_cancelled(value): | ||||||
|  |         if timed_out[0]: | ||||||
|  |             to_call = on_timeout_cancel or _cancelled_to_timed_out_error | ||||||
|  |             return to_call(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 _cancelled_to_timed_out_error(value, timeout): | ||||||
|  |     if isinstance(value, failure.Failure): | ||||||
|  |         value.trap(CancelledError) | ||||||
|  |         raise DeferredTimeoutError(timeout, "Deferred") | ||||||
|  |     return value | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user