forked from MirrorHub/synapse
		
	Merge pull request #1095 from matrix-org/erikj/batch_edus
Clobber EDUs in send queue
This commit is contained in:
		
				commit
				
					
						555460ae1b
					
				
			
		
					 5 changed files with 60 additions and 20 deletions
				
			
		synapse
|  | @ -122,8 +122,12 @@ class FederationClient(FederationBase): | |||
|             pdu.event_id | ||||
|         ) | ||||
| 
 | ||||
|     def send_presence(self, destination, states): | ||||
|         if destination != self.server_name: | ||||
|             self._transaction_queue.enqueue_presence(destination, states) | ||||
| 
 | ||||
|     @log_function | ||||
|     def send_edu(self, destination, edu_type, content): | ||||
|     def send_edu(self, destination, edu_type, content, key=None): | ||||
|         edu = Edu( | ||||
|             origin=self.server_name, | ||||
|             destination=destination, | ||||
|  | @ -134,7 +138,7 @@ class FederationClient(FederationBase): | |||
|         sent_edus_counter.inc() | ||||
| 
 | ||||
|         # TODO, add errback, etc. | ||||
|         self._transaction_queue.enqueue_edu(edu) | ||||
|         self._transaction_queue.enqueue_edu(edu, key=key) | ||||
|         return defer.succeed(None) | ||||
| 
 | ||||
|     @log_function | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ from synapse.util.retryutils import ( | |||
|     get_retry_limiter, NotRetryingDestination, | ||||
| ) | ||||
| from synapse.util.metrics import measure_func | ||||
| from synapse.handlers.presence import format_user_presence_state | ||||
| import synapse.metrics | ||||
| 
 | ||||
| import logging | ||||
|  | @ -69,13 +70,21 @@ class TransactionQueue(object): | |||
|         # destination -> list of tuple(edu, deferred) | ||||
|         self.pending_edus_by_dest = edus = {} | ||||
| 
 | ||||
|         # Presence needs to be separate as we send single aggragate EDUs | ||||
|         self.pending_presence_by_dest = presence = {} | ||||
|         self.pending_edus_keyed_by_dest = edus_keyed = {} | ||||
| 
 | ||||
|         metrics.register_callback( | ||||
|             "pending_pdus", | ||||
|             lambda: sum(map(len, pdus.values())), | ||||
|         ) | ||||
|         metrics.register_callback( | ||||
|             "pending_edus", | ||||
|             lambda: sum(map(len, edus.values())), | ||||
|             lambda: ( | ||||
|                 sum(map(len, edus.values())) | ||||
|                 + sum(map(len, presence.values())) | ||||
|                 + sum(map(len, edus_keyed.values())) | ||||
|             ), | ||||
|         ) | ||||
| 
 | ||||
|         # destination -> list of tuple(failure, deferred) | ||||
|  | @ -130,13 +139,27 @@ class TransactionQueue(object): | |||
|                 self._attempt_new_transaction, destination | ||||
|             ) | ||||
| 
 | ||||
|     def enqueue_edu(self, edu): | ||||
|     def enqueue_presence(self, destination, states): | ||||
|         self.pending_presence_by_dest.setdefault(destination, {}).update({ | ||||
|             state.user_id: state for state in states | ||||
|         }) | ||||
| 
 | ||||
|         preserve_context_over_fn( | ||||
|             self._attempt_new_transaction, destination | ||||
|         ) | ||||
| 
 | ||||
|     def enqueue_edu(self, edu, key=None): | ||||
|         destination = edu.destination | ||||
| 
 | ||||
|         if not self.can_send_to(destination): | ||||
|             return | ||||
| 
 | ||||
|         self.pending_edus_by_dest.setdefault(destination, []).append(edu) | ||||
|         if key: | ||||
|             self.pending_edus_keyed_by_dest.setdefault( | ||||
|                 destination, {} | ||||
|             )[(edu.edu_type, key)] = edu | ||||
|         else: | ||||
|             self.pending_edus_by_dest.setdefault(destination, []).append(edu) | ||||
| 
 | ||||
|         preserve_context_over_fn( | ||||
|             self._attempt_new_transaction, destination | ||||
|  | @ -190,8 +213,13 @@ class TransactionQueue(object): | |||
|             while True: | ||||
|                     pending_pdus = self.pending_pdus_by_dest.pop(destination, []) | ||||
|                     pending_edus = self.pending_edus_by_dest.pop(destination, []) | ||||
|                     pending_presence = self.pending_presence_by_dest.pop(destination, {}) | ||||
|                     pending_failures = self.pending_failures_by_dest.pop(destination, []) | ||||
| 
 | ||||
|                     pending_edus.extend( | ||||
|                         self.pending_edus_keyed_by_dest.pop(destination, {}).values() | ||||
|                     ) | ||||
| 
 | ||||
|                     limiter = yield get_retry_limiter( | ||||
|                         destination, | ||||
|                         self.clock, | ||||
|  | @ -203,6 +231,22 @@ class TransactionQueue(object): | |||
|                     ) | ||||
| 
 | ||||
|                     pending_edus.extend(device_message_edus) | ||||
|                     if pending_presence: | ||||
|                         pending_edus.append( | ||||
|                             Edu( | ||||
|                                 origin=self.server_name, | ||||
|                                 destination=destination, | ||||
|                                 edu_type="m.presence", | ||||
|                                 content={ | ||||
|                                     "push": [ | ||||
|                                         format_user_presence_state( | ||||
|                                             presence, self.clock.time_msec() | ||||
|                                         ) | ||||
|                                         for presence in pending_presence.values() | ||||
|                                     ] | ||||
|                                 }, | ||||
|                             ) | ||||
|                         ) | ||||
| 
 | ||||
|                     if pending_pdus: | ||||
|                         logger.debug("TX [%s] len(pending_pdus_by_dest[dest]) = %d", | ||||
|  |  | |||
|  | @ -625,18 +625,8 @@ class PresenceHandler(object): | |||
|         Args: | ||||
|             hosts_to_states (dict): Mapping `server_name` -> `[UserPresenceState]` | ||||
|         """ | ||||
|         now = self.clock.time_msec() | ||||
|         for host, states in hosts_to_states.items(): | ||||
|             self.federation.send_edu( | ||||
|                 destination=host, | ||||
|                 edu_type="m.presence", | ||||
|                 content={ | ||||
|                     "push": [ | ||||
|                         _format_user_presence_state(state, now) | ||||
|                         for state in states | ||||
|                     ] | ||||
|                 } | ||||
|             ) | ||||
|             self.federation.send_presence(host, states) | ||||
| 
 | ||||
|     @defer.inlineCallbacks | ||||
|     def incoming_presence(self, origin, content): | ||||
|  | @ -723,13 +713,13 @@ class PresenceHandler(object): | |||
|             defer.returnValue([ | ||||
|                 { | ||||
|                     "type": "m.presence", | ||||
|                     "content": _format_user_presence_state(state, now), | ||||
|                     "content": format_user_presence_state(state, now), | ||||
|                 } | ||||
|                 for state in updates | ||||
|             ]) | ||||
|         else: | ||||
|             defer.returnValue([ | ||||
|                 _format_user_presence_state(state, now) for state in updates | ||||
|                 format_user_presence_state(state, now) for state in updates | ||||
|             ]) | ||||
| 
 | ||||
|     @defer.inlineCallbacks | ||||
|  | @ -988,7 +978,7 @@ def should_notify(old_state, new_state): | |||
|     return False | ||||
| 
 | ||||
| 
 | ||||
| def _format_user_presence_state(state, now): | ||||
| def format_user_presence_state(state, now): | ||||
|     """Convert UserPresenceState to a format that can be sent down to clients | ||||
|     and to other servers. | ||||
|     """ | ||||
|  | @ -1101,7 +1091,7 @@ class PresenceEventSource(object): | |||
|         defer.returnValue(([ | ||||
|             { | ||||
|                 "type": "m.presence", | ||||
|                 "content": _format_user_presence_state(s, now), | ||||
|                 "content": format_user_presence_state(s, now), | ||||
|             } | ||||
|             for s in updates.values() | ||||
|             if include_offline or s.state != PresenceState.OFFLINE | ||||
|  |  | |||
|  | @ -156,6 +156,7 @@ class ReceiptsHandler(BaseHandler): | |||
|                             } | ||||
|                         }, | ||||
|                     }, | ||||
|                     key=(room_id, receipt_type, user_id), | ||||
|                 ) | ||||
| 
 | ||||
|     @defer.inlineCallbacks | ||||
|  |  | |||
|  | @ -187,6 +187,7 @@ class TypingHandler(object): | |||
|                         "user_id": user_id, | ||||
|                         "typing": typing, | ||||
|                     }, | ||||
|                     key=(room_id, user_id), | ||||
|                 )) | ||||
| 
 | ||||
|         yield preserve_context_over_deferred( | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue