Skip to content

Expose MSC4354 Sticky Events over MSC4186 (Simplified) Sliding Sync. - #19591

Merged
reivilibre merged 29 commits into
developfrom
rei/sticky_events_sliding_sync
Jun 23, 2026
Merged

Expose MSC4354 Sticky Events over MSC4186 (Simplified) Sliding Sync.#19591
reivilibre merged 29 commits into
developfrom
rei/sticky_events_sliding_sync

Conversation

@reivilibre

@reivilibre reivilibre commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Follows: #19487
Part of: MSC4354 whose experimental feature tracking issue is #19409

This PR implements the Sliding Sync (MSC4186) extension described in MSC4354, allowing sliding sync clients
to receive sticky events in a reliable way.

The logic is much the same as for oldschool sync (implementation in #19487),
although in the sliding sync extension, the client can choose their own limit
and must control their own pagination through an extra token in the extension request/response bodies.

EDIT: Note this PR does not yet send down existing sticky events in the room when the room has been newly-joined.
This newly-discovered gap is tracked at #19662 and will be addressed for both current sync and MSC4186 SSS soon.


This pull request is commit-by-commit review friendly.

  1. Add gather_optional_coroutines/7 overload

  2. Add fields for sticky events sliding sync extension

  3. Add explicit Absent utility type

  4. Implement sliding sync extension for sticky events

  5. Add sliding sync extension test

  6. drive-by docstring tweak on ordering

@reivilibre reivilibre changed the title Expose [MSC4354 Sticky Events](https://github.com/matrix-org/matrix-spec-proposals/pull/4354) over [MSC4186 (Simplified) Sliding Sync](https://github.com/matrix-org/matrix-spec-proposals/pull/4186). Expose MSC4354 Sticky Events over MSC4186 (Simplified) Sliding Sync. Mar 20, 2026
Comment thread synapse/util/sentinel.py Outdated
Comment thread synapse/handlers/sliding_sync/extensions.py Outdated
@reivilibre
reivilibre force-pushed the rei/sticky_events_sliding_sync branch 4 times, most recently from 360c60b to adb3191 Compare March 20, 2026 16:20
Comment thread pyproject.toml Outdated
@reivilibre
reivilibre force-pushed the rei/sticky_events_sliding_sync branch from 97efd43 to 6883dcd Compare March 20, 2026 17:24
@reivilibre
reivilibre marked this pull request as ready for review March 20, 2026 17:25
@reivilibre
reivilibre requested a review from a team as a code owner March 20, 2026 17:25
Comment thread synapse/handlers/sliding_sync/extensions.py Outdated
Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
Fixes
builtins.NotImplementedError: Cannot check isinstance when validating
from json, use a JsonOrPython validator instead.
This reverts commit 6883dcd.

EPEL 10 only had 2.9.2 so try to work around issue without updating
builtins.NotImplementedError: Cannot check isinstance when validating
from json, use a JsonOrPython validator instead.
@reivilibre
reivilibre force-pushed the rei/sticky_events_sliding_sync branch from 6883dcd to c5c1b01 Compare April 7, 2026 16:14
@reivilibre
reivilibre requested review from a team and erikjohnston and removed request for erikjohnston April 7, 2026 17:44
Comment thread synapse/types/__init__.py Outdated
Comment thread synapse/types/__init__.py
Comment thread synapse/types/__init__.py
Comment thread synapse/types/__init__.py Outdated
Comment thread synapse/util/sentinel.py Outdated
Comment on lines +1008 to +1020
since_token = sticky_events_request.since or SlidingSyncStickyEventsToken(
sticky_events_stream_id=0
)
(
sticky_events_to_id,
room_to_event_ids,
) = await self.store.get_sticky_events_in_rooms(
all_interested_room_ids,
from_id=since_token.sticky_events_stream_id,
to_id=to_token.sticky_events_key,
now=now,
limit=min(sticky_events_request.limit, StickyEvent.MAX_EVENTS_IN_SYNC),
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Sticky Events extension having it's own pagination inside Sliding Sync seems like a smell to me.

Related discussion: matrix-org/matrix-spec-proposals#4354 (comment)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find the linked discussion (GH deep links not working atm) but I trust that it captures the essence of the smell enough?

I broadly agree; in fact I'd go so far as to say that sliding sync is missing a high-level steward who sets the strategy for pagination. I have opened matrix-org/matrix-spec#2378 to describe this but not sure how to 'anchor' this down anywhere or find the right outcome for it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating the issue. Given the to_device extension already uses this pattern, I guess we can opt to use it as well. Holding on to the hope that we don't settle.

I'm not really convinced it's the way to go. It's basically introducing it's own pagination behavior compared to the normal part of the Sliding Sync response. For the normal Sliding Sync response, the "No pagination" pattern is just to return all of the latest unseen data and if there is too much data (they've been offline too long and the homeserver deems it will take too many resources to compile their response, or the response is too large), reset the connection (M_UNKNOWN_POS) which tells the client to start over. I think that last detail should be added to matrix-org/matrix-spec#2378

And my general thoughts for sticky events is summarized in matrix-org/matrix-spec-proposals#4354 (comment) which was resolved for some reason 😠

Comment thread synapse/types/rest/client/__init__.py
Comment thread synapse/types/rest/client/__init__.py
Comment thread tests/rest/client/sliding_sync/test_extension_sticky_events.py
Comment thread tests/rest/client/sliding_sync/test_extension_sticky_events.py
@reivilibre
reivilibre force-pushed the rei/sticky_events_sliding_sync branch from f5b8de3 to aa20913 Compare June 15, 2026 13:14
Comment thread synapse/types/rest/client/__init__.py Outdated
Comment thread synapse/handlers/sliding_sync/extensions.py Outdated
Comment thread tests/rest/client/sliding_sync/test_extension_sticky_events.py
Comment on lines +1008 to +1020
since_token = sticky_events_request.since or SlidingSyncStickyEventsToken(
sticky_events_stream_id=0
)
(
sticky_events_to_id,
room_to_event_ids,
) = await self.store.get_sticky_events_in_rooms(
all_interested_room_ids,
from_id=since_token.sticky_events_stream_id,
to_id=to_token.sticky_events_key,
now=now,
limit=min(sticky_events_request.limit, StickyEvent.MAX_EVENTS_IN_SYNC),
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating the issue. Given the to_device extension already uses this pattern, I guess we can opt to use it as well. Holding on to the hope that we don't settle.

I'm not really convinced it's the way to go. It's basically introducing it's own pagination behavior compared to the normal part of the Sliding Sync response. For the normal Sliding Sync response, the "No pagination" pattern is just to return all of the latest unseen data and if there is too much data (they've been offline too long and the homeserver deems it will take too many resources to compile their response, or the response is too large), reset the connection (M_UNKNOWN_POS) which tells the client to start over. I think that last detail should be added to matrix-org/matrix-spec#2378

And my general thoughts for sticky events is summarized in matrix-org/matrix-spec-proposals#4354 (comment) which was resolved for some reason 😠

Comment thread synapse/types/rest/client/__init__.py
Comment thread synapse/handlers/sliding_sync/extensions.py Outdated
Comment thread tests/rest/client/sliding_sync/test_extension_sticky_events.py Outdated
@reivilibre
reivilibre enabled auto-merge (squash) June 22, 2026 16:16
@reivilibre
reivilibre merged commit 16fe5fb into develop Jun 23, 2026
178 of 186 checks passed
@reivilibre
reivilibre deleted the rei/sticky_events_sliding_sync branch June 23, 2026 13:04
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Jul 7, 2026
Tested on NetBSD 10 amd64 with 2026Q2 environment.

# Synapse 1.156.0 (2026-07-07)

## Features

- Expose [MSC4354 Sticky Events](matrix-org/matrix-spec-proposals#4354) over [MSC4186 (Simplified) Sliding Sync](matrix-org/matrix-spec-proposals#4186). ([\#19591](element-hq/synapse#19591))
- Stabilize support for sending ephemeral events to application services, as per [MSC2409](matrix-org/matrix-spec-proposals#2409). Contributed by @jason-famedly @ Famedly. ([\#19758](element-hq/synapse#19758))
- Include `allowed_room_ids` in the `/summary` client-server API response for rooms with restricted join rules, as required by Matrix 1.15.
  Contributed by @FrenchGithubUser @famedly. ([\#19762](element-hq/synapse#19762))
- [MSC4140: Cancellable delayed events](matrix-org/matrix-spec-proposals#4140): Allow authentication on delayed event management endpoints (such as `/restart`) to bypass ratelimits for unauthenticated requests based on the client IP address. ([\#19794](element-hq/synapse#19794))
- Add new metric `synapse_non_deactivated_user_count` which tracks the number of non-deactivated users in the database, split by `app_service`. ([\#19848](element-hq/synapse#19848))
- The `GET /_matrix/client/unstable/org.matrix.msc1763/retention/configuration` endpoint is now provided when retention
  is enabled and `experimental_features.msc1763_enabled` is enabled, based on
  [MSC1763](matrix-org/matrix-spec-proposals#1763). ([\#19853](element-hq/synapse#19853))
- Add experimental support for [MSC4491: Invite reasons in room creation](matrix-org/matrix-spec-proposals#4491). ([\#19874](element-hq/synapse#19874))


# Synapse 1.155.0 (2026-06-16)


# Synapse 1.154.0 (2026-06-04)

## Features

- Add support for [MSC4452: Preview URL capabilities API](matrix-org/matrix-spec-proposals#4452) which exposes a `io.element.msc4452.preview_url` capability.
  If `experimental_features.msc4452_enabled` is `true`, the `/_matrix/(client/v1/media|media/v3)/preview_url` endpoint
  now responds with a 403 status code when the capability is disabled. ([\#19715](element-hq/synapse#19715))


# Synapse 1.153.0 (2026-05-19)

## Features

- Make ACLs apply to EDUs per [MSC4163](matrix-org/matrix-spec-proposals#4163). ([\#18475](element-hq/synapse#18475))
- Stabilize [MSC3266: Room summary API](matrix-org/matrix-spec-proposals#3266), removing the experimental config flag `msc3266_enabled`. Contributed by @dasha-uwu. ([\#19720](element-hq/synapse#19720))
- Partial [MSC4311](matrix-org/matrix-spec-proposals#4311) implementation: `m.room.create` is now a required part of stripped `invite_state`/`knock_state` . Contributed by @FrenchGithubUser @famedly. ([\#19722](element-hq/synapse#19722))
- Expose `tombstoned` and `replacement_room` in room details on admin API endpoint `GET /_synapse/admin/v1/rooms/<room_id>`. Contributed by Noah Markert. ([\#19737](element-hq/synapse#19737))


# Synapse 1.152.1 (2026-05-07)


# Synapse 1.152.0 (2026-04-28)

## Features

- Add a ["Listing quarantined media changes" Admin API](https://element-hq.github.io/synapse/latest/admin_api/media_admin_api.html#listing-quarantined-media-changes) for retrieving a paginated record of when media became (un)quarantined. ([\#19558](element-hq/synapse#19558), [\#19677](element-hq/synapse#19677), [\#19694](element-hq/synapse#19694))
- Advertise [MSC4445](matrix-org/matrix-spec-proposals#4445) sync timeline order in `unstable_features`. ([\#19642](element-hq/synapse#19642))
- Report the Rust compiler version used in the Prometheus metrics. Contributed by Noah Markert. ([\#19643](element-hq/synapse#19643))
- Passthrough 'article' and 'profile' OpenGraph metadata on URL preview requests. ([\#19659](element-hq/synapse#19659))
- Add a way to re-sign local events with a new signing key. ([\#19668](element-hq/synapse#19668))
- Support [MSC4450: Identity Provider selection for User-Interactive Authentication with Legacy Single Sign-On](matrix-org/matrix-spec-proposals#4450). ([\#19693](element-hq/synapse#19693))
- Add experimental support for [MSC4242](matrix-org/matrix-spec-proposals#4242): State DAGs. Excludes federation support. ([\#19424](element-hq/synapse#19424))
- Adds [Admin API](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html) endpoints to
  list, fetch and delete user reports. ([\#19657](element-hq/synapse#19657))
- Reduce database disk space usage by pruning old rows from `device_lists_changes_in_room`. ([\#19473](element-hq/synapse#19473), [\#19709](element-hq/synapse#19709))


# Synapse 1.151.0 (2026-04-07)

## Features

- Add stable support for [MSC4284](matrix-org/matrix-spec-proposals#4284) Policy Servers. ([\#19503](element-hq/synapse#19503))
- Update and stabilize support for [MSC2666](matrix-org/matrix-spec-proposals#2666): Get rooms in common with another user. Contributed by @tulir @ Beeper. ([\#19511](element-hq/synapse#19511))
- Updated experimental support for [MSC4388: Secure out-of-band channel for sign in with QR](matrix-org/matrix-spec-proposals#4388). ([\#19573](element-hq/synapse#19573))
- Stabilize `room_version` and `encryption` fields in the space/room `/hierarchy` API (part of [MSC3266](matrix-org/matrix-spec-proposals#3266)). ([\#19576](element-hq/synapse#19576))
- Introduce a [configuration option](https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#matrix_authentication_service) to allow using HTTP/2 over plaintext when Synapse connects to Matrix Authentication Service. ([\#19586](element-hq/synapse#19586))

## Deprecations and Removals

- Remove support for [MSC3852: Expose user agent information on Device](matrix-org/matrix-spec-proposals#3852) as the MSC was closed. ([\#19430](element-hq/synapse#19430))


# Synapse 1.150.0 (2026-03-24)

## Features

- Add experimental support for the [MSC4370](matrix-org/matrix-spec-proposals#4370) Federation API `GET /extremities` endpoint. ([\#19314](element-hq/synapse#19314))
- [MSC4140: Cancellable delayed events](matrix-org/matrix-spec-proposals#4140): When persisting a delayed event to the timeline, include its `delay_id` in the event's `unsigned` section in `/sync` responses to the event sender. ([\#19479](element-hq/synapse#19479))
- Expose [MSC4354 Sticky Events](matrix-org/matrix-spec-proposals#4354) over the legacy (v3) /sync API. ([\#19487](element-hq/synapse#19487))
- When Matrix Authentication Service (MAS) integration is enabled, allow MAS to set the user locked status in Synapse. ([\#19554](element-hq/synapse#19554))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants