From c62c77d704e4c2aeddff2efb3eea93b1f946748c Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Thu, 7 May 2020 17:13:09 +0200 Subject: [PATCH] Add a looping call to retry resyncs --- synapse/handlers/device.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/synapse/handlers/device.py b/synapse/handlers/device.py index 16247705a3..ca307b67f2 100644 --- a/synapse/handlers/device.py +++ b/synapse/handlers/device.py @@ -535,6 +535,10 @@ class DeviceListUpdater(object): iterable=True, ) + # Attempt to resync out of sync device lists every 30s. + self._resync_retry_in_progress = False + self.clock.looping_call(self._maybe_retry_device_resync, 30 * 1000) + @trace @defer.inlineCallbacks def incoming_device_list_update(self, origin, edu_content): @@ -678,6 +682,40 @@ class DeviceListUpdater(object): return False + async def _maybe_retry_device_resync(self): + """Retry to resync device lists that are out of sync, except if another retry is + in progress. + """ + if self._resync_retry_in_progress: + return + + try: + # Prevent another call of this function to retry resyncing device lists so + # we don't send too many requests. + self._resync_retry_in_progress = True + # Get all of the users that need resyncing. + need_resync = await self.store.get_user_ids_requiring_device_list_resync() + # Iterate over the set of user IDs. + for user_id in need_resync: + # Try to resync the current user's devices list. Exception handling + # isn't necessary here, since user_device_resync catches all instances + # of "Exception" that might be raised from the federation request. This + # means that if an exception is raised by this function, it must be + # because of a database issue, which means _maybe_retry_device_resync + # probably won't be able to go much further anyway. + result = await self.user_device_resync(user_id=user_id) + # user_device_resync only returns a result if it managed to successfully + # resync and update the database. Updating the table of users requiring + # resync isn't necessary here as user_device_resync already does it + # (through self.store.update_remote_device_list_cache). + if result: + logger.debug( + "Successfully resynced the device list for %s" % user_id, + ) + finally: + # Allow future calls to retry resyncinc out of sync device lists. + self._resync_retry_in_progress = False + @defer.inlineCallbacks def user_device_resync(self, user_id): """Fetches all devices for a user and updates the device cache with them.