From 4cb0eeabdfc8a3ef7628bf9332f8f0a1598d1cef Mon Sep 17 00:00:00 2001 From: Devon Hudson Date: Thu, 9 Oct 2025 11:28:33 -0600 Subject: [PATCH] Allow SlidingSyncStreamToken in /relations --- synapse/streams/config.py | 26 +++++++++++++++++-- .../sliding_sync/test_extension_threads.py | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/synapse/streams/config.py b/synapse/streams/config.py index 9fee5bfb92..ced1723477 100644 --- a/synapse/streams/config.py +++ b/synapse/streams/config.py @@ -58,19 +58,41 @@ class PaginationConfig: from_tok_str = parse_string(request, "from") to_tok_str = parse_string(request, "to") + # Helper function to extract StreamToken from either StreamToken or SlidingSyncStreamToken format + def extract_stream_token(token_str: str) -> str: + """ + Extract the StreamToken portion from a token string. + + Handles both: + - StreamToken format: "s123_456_..." + - SlidingSyncStreamToken format: "5/s123_456_..." (extracts part after /) + + This allows clients using sliding sync to use their pos tokens + with endpoints like /relations and /messages. + """ + if "/" in token_str: + # SlidingSyncStreamToken format: "connection_position/stream_token" + # Split and return just the stream_token part + parts = token_str.split("/", 1) + if len(parts) == 2: + return parts[1] + return token_str + try: from_tok = None if from_tok_str == "END": from_tok = None # For backwards compat. elif from_tok_str: - from_tok = await StreamToken.from_string(store, from_tok_str) + stream_token_str = extract_stream_token(from_tok_str) + from_tok = await StreamToken.from_string(store, stream_token_str) except Exception: raise SynapseError(400, "'from' parameter is invalid") try: to_tok = None if to_tok_str: - to_tok = await StreamToken.from_string(store, to_tok_str) + stream_token_str = extract_stream_token(to_tok_str) + to_tok = await StreamToken.from_string(store, stream_token_str) except Exception: raise SynapseError(400, "'to' parameter is invalid") diff --git a/tests/rest/client/sliding_sync/test_extension_threads.py b/tests/rest/client/sliding_sync/test_extension_threads.py index aeace02da7..3855b03672 100644 --- a/tests/rest/client/sliding_sync/test_extension_threads.py +++ b/tests/rest/client/sliding_sync/test_extension_threads.py @@ -595,7 +595,7 @@ class SlidingSyncThreadsExtensionTestCase(SlidingSyncBase): # Now use the prev_batch token with /relations endpoint to paginate backwards channel = self.make_request( "GET", - f"/_matrix/client/v1/rooms/{room_id}/relations/{thread_root_id}?from={prev_batch}&dir=b", + f"/_matrix/client/v1/rooms/{room_id}/relations/{thread_root_id}?from={prev_batch}&to={sync_pos}&dir=b", access_token=user1_tok, ) self.assertEqual(channel.code, 200, channel.json_body)