diff --git a/synapse/handlers/sliding_sync/extensions.py b/synapse/handlers/sliding_sync/extensions.py index cacab909b7..a66ffb1224 100644 --- a/synapse/handlers/sliding_sync/extensions.py +++ b/synapse/handlers/sliding_sync/extensions.py @@ -1005,9 +1005,9 @@ class SlidingSyncExtensionHandler: if not sticky_events_request.enabled: return None now = self.clock.time_msec() - since_token = sticky_events_request.since or SlidingSyncStickyEventsToken( - sticky_events_stream_id=0 - ) + # If there is no `since` token specified, start from the beginning of the stream + # to make sure the client receives all visible (unexpired) sticky events + since_token = sticky_events_request.since or SlidingSyncStickyEventsToken.START ( sticky_events_to_id, room_to_event_ids, diff --git a/synapse/types/rest/client/__init__.py b/synapse/types/rest/client/__init__.py index 1bb4724a69..799ae746e2 100644 --- a/synapse/types/rest/client/__init__.py +++ b/synapse/types/rest/client/__init__.py @@ -19,6 +19,7 @@ # # import re +from typing import ClassVar import pydantic_core.core_schema from pydantic import ( @@ -126,6 +127,7 @@ class SlidingSyncStickyEventsToken: """ PATTERN = re.compile(r"^sticky_([0-9]+)$") + START: ClassVar["SlidingSyncStickyEventsToken"] def __init__(self, *, sticky_events_stream_id: int) -> None: self.sticky_events_stream_id = sticky_events_stream_id @@ -160,6 +162,12 @@ class SlidingSyncStickyEventsToken: return self.serialise() +# Starting reading a stream at 0 ensures all stream fact rows wlil be read +SlidingSyncStickyEventsToken.START = SlidingSyncStickyEventsToken( + sticky_events_stream_id=0 +) + + class SlidingSyncBody(RequestBodyModel): """ Sliding Sync API request body.