Skip to content

Conversation

@kegsay
Copy link
Contributor

@kegsay kegsay commented Sep 24, 2025

This implements MSC4354: Sticky Events. To enable it, set this in homeserver.yaml:

experimental_features:
    msc4354_enabled: true

Complement tests: matrix-org/complement#806

Pull Request Checklist

  • Pull request is based on the develop branch
  • Pull request includes a changelog file. The entry should:
    • Be a short description of your change which makes sense to users. "Fixed a bug that prevented receiving messages from other servers." instead of "Moved X method from EventStore to EventWorkerStore.".
    • Use markdown where necessary, mostly for code blocks.
    • End with either a period (.) or an exclamation mark (!).
    • Start with a capital letter.
    • Feel free to credit yourself, by adding a sentence "Contributed by @github_username." or "Contributed by [Your Name]." to the end of the entry.
  • Code style is correct (run the linters)

Copy link
Contributor

@MadLittleMods MadLittleMods left a comment

Choose a reason for hiding this comment

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

Looked everything over but didn't full evaluate the sticky events part against the MSC or fully ponder weird corners.

if not sticky_events_request.enabled:
return None
now = self.clock.time_msec()
from_id = from_token.stream_token.sticky_events_key if from_token else 0
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we copy this pattern?

if from_token:
from_stream_id = from_token.stream_token.thread_subscriptions_key
else:
from_stream_id = StreamToken.START.thread_subscriptions_key

# Consumers call 'get_sticky_events_in_rooms' which has `WHERE expires_at > ?`
# to filter out expired sticky events that have yet to be deleted.
DELETE_EXPIRED_STICKY_EVENTS_MS = 60 * 1000 * 60 # 1 hour
MAX_STICKY_DURATION_MS = 3600000 # 1 hour
Copy link
Contributor

Choose a reason for hiding this comment

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

In the client event creation, we should be preventing creating events that have duration greater than MAX_STICKY_DURATION_MS

Comment on lines +381 to +385
critical_auth_types = (
EventTypes.JoinRules,
EventTypes.PowerLevels,
EventTypes.Member,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Wondering how this plays with room versions. Do we need to be careful at all with forward compatibility, etc?

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we be using auth_types_for_event instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think we need to be that careful here. We will need to keep this updated if we make new room versions which break the current auth model though.

9. `groups_key`: `1` (note that this key is now unused)
10. `un_partial_stated_rooms_key`: `379`
11. `thread_subscriptions_key`: 4242
12. `sticky_events_key`: 4141
Copy link
Contributor

Choose a reason for hiding this comment

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

Add it to the full example token above

Copy link
Contributor

@reivilibre reivilibre left a comment

Choose a reason for hiding this comment

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

I'm taking over this PR and the MSC.

This is my initial review, cross-corroborating with the MSC.
A good chunk of it is notes for myself.

Comment on lines 567 to 569
await self._transaction_manager.send_new_transaction(
new_server, sticky_events, []
)
Copy link
Contributor

Choose a reason for hiding this comment

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

sticky_events is of unbounded length and can't be safely sent in a single federation /send request

if sticky_events:
# *prepend* these to the extrem list, so they are processed first.
# This ensures they will show up before the forward extrem in stream order
extrem_events = sticky_events + extrem_events
Copy link
Contributor

Choose a reason for hiding this comment

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

again, sticky_events could be of unbounded length and so it's not safe to send them all in a single federation /send request (maybe I'm missing something)


new_pdus = []
for p in extrem_events:
# We pulled this from the DB, so it'll be non-null
Copy link
Contributor

Choose a reason for hiding this comment

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

underneath this section, we filter out events that happened before the remote went offline. I'm not convinced this will reliably send sticky events to remotes that recently joined a room.

Comment on lines +665 to +669
await self.store.upsert_room_on_join(
room_id=room_id,
room_version=room_version_obj,
state_events=None,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

feels suspicious because we don't have a join event yet and we also haven't decided whether or not to mark the room as partial-state or not.
Will need to more closely review the impact of this.

groups_key=0,
un_partial_stated_rooms_key=un_partial_stated_rooms_key,
thread_subscriptions_key=thread_subscriptions_key,
sticky_events_key=sticky_events_key,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a change of plan is transpiring and we won't need to include this in StreamToken anymore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants