Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
4fd17d4
MSC4140: finalised delayed events, and more
AndrewFerr Oct 10, 2025
bc0e1a3
Add changelog
AndrewFerr Oct 10, 2025
4a7e78c
Work around Postgres-only error
AndrewFerr Oct 10, 2025
99f8501
Rename experimental config per suggestion
AndrewFerr Oct 31, 2025
96ed87a
Add description comment to new table
AndrewFerr Oct 31, 2025
2ec54e4
Merge finalised_delayed_events into delayed_events
AndrewFerr Nov 1, 2025
048508c
Merge with 'develop': PEP585 and always RETURNING
AndrewFerr Nov 1, 2025
095eda4
Merge with 'develop': Python 3.14 support
AndrewFerr Nov 3, 2025
5cd80ed
Add finalised_ts index in background
AndrewFerr Nov 3, 2025
11c79c2
Include DelayedEventsStore in migrated DB stores
AndrewFerr Nov 3, 2025
d2aba30
Fix error code string
AndrewFerr Nov 3, 2025
e5bef01
Run UPDATE in transaction, and check rowcount
AndrewFerr Nov 3, 2025
6a5369b
Merge with 'develop': PEP604
AndrewFerr Nov 6, 2025
9a345ce
Don't fetch after UPDATE queries
AndrewFerr Nov 7, 2025
98fa5aa
Add missing return type annotation
AndrewFerr Nov 7, 2025
25ca333
Update schema change comment
AndrewFerr Nov 7, 2025
e0c412d
Remove mistaken WHERE condition
AndrewFerr Nov 12, 2025
60549ab
Add ordering info to background update
AndrewFerr Nov 13, 2025
f1383cc
Merge with 'develop' before #19152
AndrewFerr Nov 14, 2025
274d1cf
Merge with #19152
AndrewFerr Nov 14, 2025
9444a71
Bump schema change number/order
AndrewFerr Nov 14, 2025
4de1de6
Fix mistake in DELETE query
AndrewFerr Nov 14, 2025
151e820
Merge with 'develop'
AndrewFerr Nov 14, 2025
b36becc
Return most recent finalised events first
AndrewFerr Nov 14, 2025
c9eb467
Removed leading "finalised_" from object fields
AndrewFerr Nov 14, 2025
7497cb5
Raise errors on manual send of delayed event
AndrewFerr Nov 24, 2025
ded80f4
Merge with 'develop'
AndrewFerr Nov 24, 2025
58ee034
Merge branch 'upstream/develop' into msc4140-finalised-and-filters
barodeur Sep 16, 2026
4187ec1
MSC4140: store finalised_error as TEXT
barodeur Sep 16, 2026
7cace1d
MSC4140: drop the status and delay_id filters on the delayed events list
barodeur Sep 15, 2026
f9a1701
MSC4140: return finalised delayed events from GET /delayed_events/{de…
barodeur Sep 15, 2026
6fb0a6c
MSC4140: test that finalised delayed events do not count towards the …
barodeur Sep 15, 2026
9e13d9b
MSC4140: return 409 for actions that conflict with a finalised delaye…
barodeur Sep 15, 2026
2cda2c4
MSC4140: keep a delayed event scheduled if sending it manually fails
barodeur Sep 15, 2026
4095b54
MSC4140: read finalised delayed event retention config next to the us…
barodeur Sep 15, 2026
ab6b3bf
MSC4140: prune finalised delayed events in single statements
barodeur Sep 15, 2026
1293b84
Merge with 'develop'
AndrewFerr Sep 24, 2026
f1a9e3d
Merge with updates from @barodeur
AndrewFerr Sep 28, 2026
f988e91
Fix test for usage with room v12 creators
AndrewFerr Sep 28, 2026
7c041c1
Return None, not tuple with None, for re-sending
AndrewFerr Sep 28, 2026
fa635ea
Skip looking up next send time on re-cancel
AndrewFerr Sep 28, 2026
9bcb87f
Replace "pending" with "scheduled" in docstring
AndrewFerr Sep 28, 2026
383280f
MSC4140: index finalised delayed events for the per-user retention prune
barodeur Sep 29, 2026
0b6f589
Merge rank index from @barodeur
AndrewFerr Sep 29, 2026
a87ff94
Use attr class for finalised delayed event details
AndrewFerr Oct 2, 2026
f85a1c3
Use simple_select_one
AndrewFerr Oct 2, 2026
9f852b8
Use named parameters
AndrewFerr Oct 2, 2026
b69ffa8
Remove documentation for experimental configs
AndrewFerr Oct 2, 2026
40dd2db
Move finalised retention config to experimental.py
AndrewFerr Oct 2, 2026
8d7aedc
Merge with 'develop' and its recent MSC4140 PRs
AndrewFerr Oct 14, 2026
541372e
Drop special case for state events in bulk timeout
AndrewFerr Oct 14, 2026
b2d853b
Send timed out events concurrently per room
AndrewFerr Oct 14, 2026
2eaf104
Refine tiebreakers for finalised event pruning
AndrewFerr Oct 15, 2026
d38e30c
Prune/erase finalised events immediately
AndrewFerr Oct 16, 2026
d9ef39a
Cover case of updating in-processed delayed event
AndrewFerr Oct 16, 2026
1fbd3c8
Merge with 'develop'
AndrewFerr Oct 16, 2026
22bdd67
Merge with 'develop'
AndrewFerr Oct 19, 2026
a308f30
Add finalised coverage on new tests from merge
AndrewFerr Oct 19, 2026
a0301e6
Add missing comments for delayed event waits
AndrewFerr Oct 19, 2026
bd5f615
Update copyright date on newly-added file
AndrewFerr Oct 19, 2026
02da61d
Lint
AndrewFerr Oct 19, 2026
9a6e16e
Merge with 'develop'
AndrewFerr Oct 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/19038.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add more support for MSC4140, namely the ability to inspect sent, cancelled, or failed delayed events, aka "finalised" delayed events.
Comment thread
AndrewFerr marked this conversation as resolved.

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.

Are there Complement changes to go along with this?

I see some TestDelayedEvents Complement tests that are failing: https://github.com/element-hq/synapse/actions/runs/18411628889/job/52465384686?pr=19038

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Are there Complement changes to go along with this?

No, not yet. I'll add some soon.

I see some TestDelayedEvents Complement tests that are failing

That's an unrelated failure, which has been flaky for a frustratingly long time. Maybe now is a good time to try to tackle it again.

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.

It doesn't seem flaky. It's failed all 3 times for both SQLite and Postgres. And it's only TestDelayedEvents

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Complement tests are tracked by matrix-org/complement#929

43 changes: 43 additions & 0 deletions synapse/config/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from synapse.config import ConfigError
from synapse.config._base import Config, read_file
from synapse.types import JsonDict, StrSequence
from synapse.util.duration import Duration


@cache
Expand Down Expand Up @@ -250,6 +251,48 @@ def read_config(
# MSC4133: Custom profile fields
self.msc4133_enabled: bool = experimental.get("msc4133_enabled", False)

# The portion of MSC4140 related to retention of delayed events for lookup
# after they have been finalised, i.e. sent, cancelled, or failed to be sent.
# Finalised delayed events past their retention are pruned every 5 minutes.

# How long a finalised delayed event may be retained for.
# 0 disables retention.
finalised_retention_period_ms = self.parse_duration(
experimental.get("msc4140_finalised_retention_period", "7d")
)
if finalised_retention_period_ms < 0:
raise ConfigError(
"'msc4140_finalised_retention_period' must be a non-negative duration",
("experimental", "msc4140_finalised_retention_period"),
)
self.msc4140_finalised_retention_period = Duration(
milliseconds=finalised_retention_period_ms
)

# The maximum number of finalised delayed events retained per user.
# 0 disables retention.
self.msc4140_finalised_retention_limit_per_user: int = experimental.get(
"msc4140_finalised_retention_limit_per_user", 1000
)
if (
not isinstance(self.msc4140_finalised_retention_limit_per_user, int)
or self.msc4140_finalised_retention_limit_per_user < 0
):
raise ConfigError(
"'msc4140_finalised_retention_limit_per_user' must be a non-negative integer",
("experimental", "msc4140_finalised_retention_limit_per_user"),
)

# Since setting either config to 0 disables finalised retention,
# set both to 0 if either of them are 0, so that it doesn't make
# a difference which of them had been explicitly set to 0.
if (
not self.msc4140_finalised_retention_period
or not self.msc4140_finalised_retention_limit_per_user
):
self.msc4140_finalised_retention_period = Duration()
self.msc4140_finalised_retention_limit_per_user = 0

# MSC4143: Matrix RTC Transport using Livekit Backend
self.msc4143_enabled: bool = experimental.get("msc4143_enabled", False)

Expand Down
3 changes: 2 additions & 1 deletion synapse/config/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,8 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
self.max_event_delay_duration = Duration()

# The maximum number of delayed events a user may have scheduled at a time.
# (Defined here despite being experimental to be near the other MSC4140 config)
# (Defined here despite being experimental to be near the other MSC4140 config,
# because either config controls whether delayed events are enabled or not)
experimental = config.get("experimental_features") or {}
self.max_delayed_events_per_user: int = experimental.get(
"msc4140_max_delayed_events_per_user", 100
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/deactivate_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async def deactivate_account(
# Cancel the user's delayed events (MSC4140). Do this first, so that none
# of them get sent while the rest of the deactivation is in progress.
await self._delayed_events_handler.cancel_all_for_user(
get_localpart_from_id(user_id)
get_localpart_from_id(user_id), erase_data
)

# FIXME: Theoretically there is a race here wherein user resets
Expand Down
Loading
Loading