diff --git a/synapse/rest/client/sync.py b/synapse/rest/client/sync.py index 2b103ca6a8..c857c658ce 100644 --- a/synapse/rest/client/sync.py +++ b/synapse/rest/client/sync.py @@ -45,7 +45,7 @@ from synapse.http.server import HttpServer from synapse.http.servlet import RestServlet, parse_boolean, parse_integer, parse_string from synapse.http.site import SynapseRequest from synapse.logging.opentracing import trace_with_opname -from synapse.types import JsonDict, Requester, StreamToken +from synapse.types import JsonDict, Requester, RoomStreamToken, StreamToken from synapse.util import json_decoder from ._base import client_patterns, set_timeline_upper_limit @@ -238,9 +238,52 @@ class SyncRestServlet(RestServlet): time_now, sync_result, requester, filter_collection ) + if ( + since_token is not None + and sync_result.next_batch is not None + and self._sync_token_went_backwards( + since_token.room_key, sync_result.next_batch.room_key + ) + ): + since_str = await since_token.to_string(self.store) + next_str = await sync_result.next_batch.to_string(self.store) + logger.warning( + "sync token went backwards! from %s to %s", since_str, next_str + ) + logger.debug("Event formatting complete") return 200, response_content + def _sync_token_went_backwards( + self, since: RoomStreamToken, next: RoomStreamToken + ) -> bool: + """ + Returns true if and only if the given token went backwards. + """ + if next.stream < since.stream: + return True + + if since.instance_map: + for instance, pos in since.instance_map.items(): + if ( + next.instance_map + and next.instance_map.get(instance, next.stream) < pos + ): + return True + elif next.stream < pos: + return True + + if next.instance_map: + for instance, pos in next.instance_map.items(): + if since.instance_map and pos < since.instance_map.get( + instance, since.stream + ): + return True + elif pos < since.stream: + return True + + return False + @trace_with_opname("sync.encode_response") async def encode_response( self,