Commit Graph
377 Commits
Author SHA1 Message Date
Erik JohnstonandClaude Opus 5.5 45b0dd1d1c Encode Jaeger spans as thrift emitBatch messages in Rust
Rust spans will go to the same Jaeger agent as Python's, over UDP, as
the `Agent.emitBatch` oneway message in the thrift compact protocol.
This adds a write-only encoder for that message and the six structs in
`jaeger.thrift`, with no new dependency.

Spans are encoded one at a time so a reporter knows each span's size
before it joins them into a batch, and `emit_batch_len` bounds a
batch's size without building it.

The output matches jaeger-client's own reporter byte for byte. The
golden fixture is generated by
`scripts-dev/generate_jaeger_thrift_fixture.py` with jaeger-client's
generated thrift code and covers every tag type, logs, a follows-from
reference, a 128-bit trace ID, IDs at or above 2^63 (which thrift
sends negative) and long list headers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4zxygfJC93SsugxskhoJG
2026-10-19 08:46:01 +00:00
Erik JohnstonandClaude Opus 5.5 8ae4e7d6b1 Add a Postgres proxy that counts round trips, and use it in the bench
`scripts-dev/pg_roundtrip_proxy.py` sits between Synapse and Postgres. It
counts round trips, a client message after a server message on the same
connection, can add latency to each, and records the protocol messages
and SQL of each round trip. SIGUSR2 resets it and SIGUSR1 writes the
counts and log to a file.

`createroom_bench.py --proxy-delay-ms N` runs the server through it and
reports the round trips per request beside the timings. With a delay,
the extra wall time over a run without one shows how many of those round
trips the request waits for in turn. A new `e2ee_invite` scenario is the
room the E2EE monitor creates on jki.re, and `--scenarios` picks a
subset. `persist_bench.Server` honours `PGPORT`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVLsNh6akt4ifEizY4D1ta
2026-10-18 19:33:45 +00:00
Erik JohnstonandClaude Opus 5.5 99472ba3cf Count native pool statement-cache misses and retired connections
Each connection of the native Postgres pool caches its prepared
statements. A miss costs a round trip to prepare, and the cache is
emptied whole when it reaches 512 statements. Nothing showed how often
either happens, or how often `txn_limit` replaces a connection and loses
its cache.

The pool now counts cache hits, prepares, cache clears, and connections
opened and retired. Python reports them per pool as
`synapse_rust_db_pool_statement_cache_hits_total`,
`..._statement_prepares_total`, `..._statement_cache_clears_total`,
`..._connections_opened_total` and `..._connections_retired_total`,
carried over when the native pool is closed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVLsNh6akt4ifEizY4D1ta
2026-10-18 19:31:10 +00:00
Erik JohnstonandClaude Opus 5.5 2c9cc90926 Benchmark /createRoom with rust_room_creation
`createroom_bench.py` takes levels such as `full+rooms`, which add
`rust_room_creation: on` to a `rust_event_persistence` level, and runs
`off`, `full` and `full+rooms` by default. `persist_bench.Server` takes
extra experimental features for that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVLsNh6akt4ifEizY4D1ta
2026-10-18 17:55:28 +00:00
Erik JohnstonandClaude Opus 5.5 4dd87ff58a Add /createRoom benchmarks and fix the template DB under the Rust driver
`tests/rest/client/bench_createroom.py` times room creation per room in
the trial harness, with optional cProfile dumps and per-room counts of
database interactions and SQL statements. It skips unless
`SYNAPSE_BENCH_CREATEROOM` is set.

`scripts-dev/createroom_bench.py` times it against a real server, reusing
`persist_bench.Server`. That server now lifts the room-creation rate limit
and can run on psycopg2 instead of the native driver.

The test template database's maintenance connection now always uses
psycopg2, as `setup_test_homeserver` does. The Rust driver's `postgres`
module has no `connect`, so it failed under `SYNAPSE_TEST_RUST_DRIVER=1`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVLsNh6akt4ifEizY4D1ta
2026-10-18 16:09:03 +00:00
Erik JohnstonandClaude Opus 5.5 832be1634d Merge erikj/rust-sss-queries into the Rust event persistence branch
Brings Rust sliding sync (erikj/rust-sss-queries) together with Rust
event persistence (erikj/rust-persist-validate). Both branch from
a78b02b55c.

The conflicts were both sides adding parallel entries:
- the Complement and test environment switches
- the `RustHandlers` fields and getters
- the `_BlockingRustCalls` types

These keep both. `RustHandlers` builds the persister and the sliding sync
handler in one pass over the native pool. `SyncReader::begin` keeps the
persist side's flag-before-BEGIN and the sliding sync side's transaction
count and `begin_write`. Both sides had added the `invite_room_state`
and `knock_room_state` accessors to `Unsigned`, so one copy is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVLsNh6akt4ifEizY4D1ta
2026-10-18 10:54:17 +00:00
Erik JohnstonandClaude Opus 5.5 c7bec795fb Add a benchmark of event persistence at each Rust level
`scripts-dev/persist_bench.py` starts a real Synapse process per
`rust_event_persistence` level, on a fresh Postgres database with the
native driver, and runs the same workloads through the client API:
concurrent messages, membership churn, joins into a room with many
state events, and a redaction storm. For each, it reports wall time,
the CPU of the reactor thread and of the process, the change in
resident memory, and the `persist_events` transactions from the metrics
endpoint.

On this sandbox, 20 users, two runs of each level:

    workload         level        ms/event   txn ms   proc CPU s
    messages         off             19.7     56.7       29.1
    messages         full            14.4      4.2       23.6
    membership       off             49.6      7.4        9.5
    membership       full            41.3      4.4        8.0
    big_state_joins  off             58.1      7.7        1.05
    big_state_joins  full            50.5      4.7        0.93
    redactions       off             13.1     38.5        3.2
    redactions       full            11.5      7.1        3.2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LXMkcZVkcZhi21augBff4a
2026-10-18 10:35:53 +00:00
Erik JohnstonandClaude Opus 5.5 a05a064643 Add the Rust event persister and what it builds on
Phase 0 of the event persistence plan, apart from the write transaction
helper:

- `experimental_features.rust_event_persistence`, one ordered level
  (off, shadow, prepare, transaction, full). Nothing uses the levels yet
  beyond building the persister.
- `RustHandlers.persister`: built on the events writer when the level is not
  off and the main database uses the native driver. It holds the pool, the
  shared caches and the events, backfill and cache stream trackers.
- `PersistEffects`, the Python cache updates a Rust transaction will ask for
  in place of `txn.call_after`, applied in one call by
  `DataStore._apply_rust_persist_effects`. A test persists batches through
  Python and checks that applying the matching effects updates the same
  caches. The chunk's stream IDs come back unfinished and are finished last,
  as Python's `get_next_mult` does after the transaction's callbacks, so
  the current token never passes an event the stream change caches don't
  know about.
- `PersistContext`, read from an `EventContext` once per event.
- `Event::to_persistence_value` and `EventInternalMetadata::to_persistence_value`:
  the `event_json` columns built without the GIL.
- Rust-side persistence counters, added to the Python metrics by a pre-collect
  hook. A homeserver can now register more than one such hook. The persisted
  position is reported only when it moved, so it can't pull back the gauge
  the Python path sets.
- `SYNAPSE_TEST_RUST_PERSIST` for trial and `RUST_PERSIST` for Complement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UHKYPSc37kWqGACn9aKxKL
2026-10-16 13:06:06 +00:00
Erik JohnstonandClaude Opus 5.5 d63740fc30 Add the rust_sliding_sync option and a Rust SlidingSyncHandler
Phase 0 of the sliding sync port (renders/sliding-sync-rust-plan.md). No
behaviour change: nothing calls the Rust handler yet.

- `experimental_features.rust_sliding_sync: off | on`. There is no shadow
  mode. Booleans are accepted, as for `rust_sync`.
- `synapse_rust.sliding_sync.SlidingSyncHandler`, built by `RustHandlers`
  on the native driver only. It shares the v2 sync handler's `SyncStore`
  and carries the pool, deferred and blocking helpers the later phases'
  entry points use.
- `SlidingSyncStats`, observed per request into the
  `synapse_sliding_sync_rust_*` histograms. `SyncDbStats` now counts the
  transactions a reader begins.
- The `synapse_sliding_sync_rust_rooms_total` and
  `synapse_sliding_sync_rust_requests_total` counters.
- `SYNAPSE_TEST_RUST_SLIDING_SYNC` and `_STRICT` for trial, with the handler
  wrapped in `_BlockingRustCalls`, and `RUST_SLIDING_SYNC` for Complement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5b7Ruy4cgt27Mjq6Ptxbb
2026-10-16 10:19:27 +00:00
Erik JohnstonandClaude Opus 5.5 93287194f8 Do the Rust transmission loop's database work natively
On the native Postgres driver, the Rust queues' `NativeHooks` read the
device EDUs and record finished transactions through `FederationStore`,
on tokio. A transaction then takes no trip to the reactor, unless it
finishes a sticky event batch or a module wants to hear about delivered
events. Catch-up and the sticky event backlog stay Python. SQLite and
the Python Postgres driver keep the Python hooks.

Python skips the device queries for destinations with nothing new by
asking two stream change caches. Rust keeps a mirror of each, per
destination, fed by a new `StreamChangeCache.add_listener`, so it hears
of every change the caches do. The current stream positions live in
Python's ID generators, and are read under the GIL (without a reactor
trip) only when a destination has changed.

The loops now count their transactions, EDUs and requests in Rust.
`synapse.metrics.pre_collect_hooks` adds the counts to the Python
metrics when they are collected. This removes a GIL crossing on every
failed send, and from `_rust_complete`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5b7Ruy4cgt27Mjq6Ptxbb
2026-10-15 15:43:17 +00:00
Erik JohnstonandClaude Opus 5.5 ce45b3f71f Pass RUST_SYNC through to Complement homeservers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0194eNQP5weBtVMg8NKtc6VU
2026-10-14 23:14:41 +00:00
Erik JohnstonandClaude Opus 5.5 a4b08444e8 Let Complement runs set rust_state_res
RUST_STATE_RES=off|shadow|on in scripts-dev/complement.sh sets
experimental_features.rust_state_res in the shared homeserver config.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ULdieJyQoHNzeHq42H2M1p
2026-10-13 11:13:37 +00:00
Erik JohnstonandClaude Fable 5.1 d4c8dadaa6 Run the Rust Postgres driver in CI
The driver's Rust tests are gated on a live server and CI's bare
`cargo test` skipped them all, and nothing ran trial or Complement
through the driver. Give the cargo-test job a Postgres service, add a
trial matrix cell with `SYNAPSE_TEST_RUST_DRIVER=1`, and a Complement
cell that passes `RUST_DRIVER=1` through `complement.sh` to the image's
`SYNAPSE_USE_RUST_DRIVER`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ULdieJyQoHNzeHq42H2M1p
2026-10-12 18:55:01 +00:00
Eric Eastwood e6cc157cbd Update release script to check more often for actions being completed (every 1m) (#20093)
(`_wait_for_actions`)

Spawning from seeing the release CI being complete but needing to wait
up to 5 minutes longer to continue on.

### Dev notes

Originally the waiting was introduced in
https://github.com/matrix-org/synapse/pull/13483

GitHub rate limit:

> The primary rate limit for unauthenticated requests is 60 requests per
hour.
>
> *-- https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2026-03-10#primary-rate-limit-for-unauthenticated-users*
2026-08-12 11:54:53 -05:00
Olivier 'reivilibre d80a4e69da Dust off make_full_schema and add CI using it to show schema diffs. (#20027)
It seems a lot of time in our trial tests goes towards setting up the
database. (The same is probably true of Complement too)

We haven't done a full schema for about 20 schema versions, so no
surprise!

As a result, I want to produce a full schema soon.

In this PR I dust off `make_full_schema.sh` (which seems to have broken
after some SQLite changes)
and add a CI workflow that runs it (producing a diff) when someone
changes the schema.

The CI workflow also adds a sticky comment showing the diff on the
schema, so you can better appreciate the final effect of a change.

---

**Dead changes:**

I wanted to make it possible to generate a versioned full schema without
the manual work,
but you can't run the background updates without essentially starting up
a homeserver,
at which point it might fail because you haven't run all the deltas yet.

There's no actual good way to do this, short of deleting the latest
deltas (+ tweaking code to not crash without them)
or rolling back in the git history.

Backed out those changes, but they're preserved on the PR if interesting.

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-08-11 12:55:59 +01:00
c5f02a9313 Introduce support for MSC4429: Profile Updates for Legacy Sync (#19556)
Implements support for [MSC4429: Profile Updates for Legacy
Sync](https://github.com/matrix-org/matrix-spec-proposals/pull/4429).

Paired with https://github.com/matrix-org/complement/pull/849 and
https://github.com/matrix-org/sytest/tree/anoa/msc4429

Tracking issue for removing unstable identifiers in Synapse:
https://github.com/element-hq/synapse/issues/19891
Further improvements tracked in:
https://github.com/element-hq/synapse/issues/19981

---------

Co-authored-by: Half-Shot <will@half-shot.uk>
Co-authored-by: Jason Robinson <jasonr@element.io>
Co-authored-by: Olivier 'reivilibre' <oliverw@element.io>
2026-08-06 15:35:07 +01:00
Olivier 'reivilibre 320265f09b Remove broken DROP statements for SQLite in make_full_schema script. (#20028)
Broken out of #20027 because I'd like to have it land first.

> It seems a lot of time in our trial tests goes towards setting up the
database. (The same is probably true of Complement too)
> 
> We haven't done a full schema for about 20 schema versions, so no
surprise!
> 
> As a result, I want to produce a full schema soon.

When running `make_full_schema.sh`, these drop statements now cause the
error:

```
Parse error near line 2: table event_search_content may not be dropped
Parse error near line 3: table event_search_segments may not be dropped
Parse error near line 4: table event_search_segdir may not be dropped
Parse error near line 5: table event_search_docsize may not be dropped
Parse error near line 6: table event_search_stat may not be dropped
Parse error near line 7: table user_directory_search_content may not be dropped
Parse error near line 8: table user_directory_search_segments may not be dropped
Parse error near line 9: table user_directory_search_segdir may not be dropped
Parse error near line 10: table user_directory_search_docsize may not be dropped
Parse error near line 11: table user_directory_search_stat may not be dropped
```

It seems SQLite has cracked down on code that edits the internal tables.

Because SQLite dumps the schema with `CREATE TABLE IF NOT EXISTS` for
these virtual tables, it's harmless to leave them in the schema dump.

---------

Signed-off-by: Olivier 'reivilibre' <oliverw@matrix.org>
2026-08-06 10:15:21 +01:00
Eric Eastwood 2c8bf9a3ab Drop support for Ubuntu 25.10 'Questing Quokka', add support for Ubuntu 26.04 'Resolute Raccoon' (#20039)
Fix https://github.com/element-hq/synapse/issues/20031

### Dev notes

 - https://endoflife.date/ubuntu
 - https://endoflife.date/debian
 - https://endoflife.date/python

Finding Python version on distros:

 - https://packages.debian.org/trixie/python3
 - https://packages.ubuntu.com/resolute/python3
2026-08-04 09:08:19 -05:00
Eric Eastwood f61950d54d Fix release announcement to link to correct release branch of changelog (#20023)
Without this change, it was linking to `develop` as we were on the
`develop` branch because of the previous `merge-back` step at this point
in the release process.

Follow-up to https://github.com/element-hq/synapse/pull/19984 as this
was an oversight and I assumed we would still be on the `release-v1.158`
branch by that point.
2026-07-31 13:58:20 -05:00
Eric Eastwood 1a1af7b622 Link to changelog instead of duplicating content in the tag/release (#19984)
This means we can point to a single source of truth instead of
duplicating the content to the tag and GitHub release. Less to manage
and worry about when you make some updates to the changelog (maintenance
burden). We also get to avoid the content sitting in the vendor lock-in
GitHub releases.

We point to
`https://github.com/element-hq/synapse/blob/{repo.active_branch.name}/CHANGES.md`
as it will have the relevant changelog entry at the top and won't change
as we archive releases on `develop`. Even for RC releases after the main
release goes out, the entry will still be towards the top. We could try
to get the heading anchor for the specific section but I thought that it
wasn't necessary (nice but more complex).
2026-07-28 15:44:26 -05:00
Eric Eastwood d930ac615b Update release script JSON schema find/replace to be compatible with macOS (#19962)
BSD vs GNU `sed` problems:
```shell
$ sed -i '0,/^\$id: .*/s||$id: https://element-hq.github.io/synapse/schema/synapse/v1.157/synapse-config.schema.json|' schema/synapse-config.schema.yaml
sed: 1: "schema/synapse-config.s ...": bad flag in substitute command: 'h'
```
2026-07-15 12:01:09 -05:00
Eric Eastwood 4679ed4b06 Silencing alerts is no longer necessary during a deploy (release script instructions) (#19968)
As discussed in
[`#element-backend-internal:matrix.org`](https://matrix.to/#/!SGNQGPGUwtcPBUotTL:matrix.org/$29ZzRe7gg62UZmT0bgeseMs320Kb-Ub6DyaQE20-3ng?via=jki.re&via=element.io&via=matrix.org)

Our assumptions on why this was done previously: in the olden days you'd
get paged doing the redeploy even if everything was actually fine
(probably before we started doing rolling restarts?)
2026-07-15 11:45:52 -05:00
Olivier 'reivilibre f2f159d6c1 Fix release script considering any workflow completion as successful. (#19843)
When building the v1.155.0rc1, the release notification said the
workflow was successful
but it had actually failed.

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-06-15 12:29:49 +01:00
Andrew Morgan 2c412ba24a complement.sh: ensure old complement checkout files are deleted; remove -N wget flag (#19592) 2026-03-20 16:30:03 +00:00
Eric Eastwood 6254e009bb Fix Build and push complement image CI job pointing to non-existent image (#19523)
❌
https://github.com/element-hq/synapse/actions/runs/22609655282/job/65509315002#step:8:39
```
Error response from daemon: No such image: complement-synapse:latest
```

Regressed in
https://github.com/element-hq/synapse/pull/19475#discussion_r2823157623
where we updated `complement.sh` to build `localhost/complement-synapse`
instead of `complement-synapse`.
2026-03-16 21:56:16 -05:00
Eric Eastwood e30001883c Add in-repo Complement test to sanity check Synapse version matches git checkout (#19476)
This way we actually detect problems like
https://github.com/element-hq/synapse/pull/19475 as they happen instead
of being invisible until something breaks.

Sanity check that Complement is testing against your code changes
(whether it be local or from the PR in CI).

```
COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh --in-repo -run TestSynapseVersion
```
2026-03-11 15:30:32 -05:00
c3af44339c Fix /sync missing membership in state_after (re-introduce) (#19460)
*This PR was originally only to enable
[MSC4222](https://github.com/matrix-org/matrix-spec-proposals/pull/4222)
Complement tests (`/sync` `state_after`) but after merging the [fix
PR](https://github.com/element-hq/synapse/pull/19463), we discovered
that while the tests pass locally, [fail in
CI](https://github.com/element-hq/synapse/pull/19460#discussion_r2818080879).
To unblock the RC, we decided to revert the fix PR (see
https://github.com/element-hq/synapse/pull/19474#discussion_r2818061001
for more info). To better ensure tests actually pass in CI, we're
re-introducing the fix here in the same PR that we enable the tests in.*

---

Fix `/sync` missing membership in `state_after`.

This applies to any scenario where the first membership has a different
`sender` compared to the `state_key` and then the second membership has
the same `sender`/`state_key`. Like someone inviting another person and
then them joining. Or someone being kicked and then they leave.

This bug has been present since the MSC4222 implementation was
introduced into the codebase
(https://github.com/element-hq/synapse/pull/17888).

---

Fix https://github.com/element-hq/synapse/issues/19455
Fix https://github.com/element-hq/customer-success/issues/656

I have a feeling, this might also fix these issues (will close and see
how people report back):

Fix https://github.com/element-hq/synapse/issues/18182
Fix https://github.com/element-hq/synapse/issues/19478

 ### Testing strategy

Complement tests: https://github.com/matrix-org/complement/pull/842

We will need https://github.com/element-hq/synapse/pull/19460 to merge
in order to enable the Complement tests in Synapse but this PR should be
merged first so they pass in the first place. I've tested locally that
the Complement tests pass with this fix.




### Dev notes


[MSC4222](https://github.com/matrix-org/matrix-spec-proposals/pull/4222)
has already been merged into the spec and is already part of Matrix
v1.16 but we haven't [stabilized support in Synapse
yet](https://github.com/element-hq/synapse/issues/19414).

---

In the same ballpark:

 - https://github.com/element-hq/synapse/issues/19455
 - https://github.com/element-hq/synapse/issues/17050
 - https://github.com/element-hq/synapse/issues/17430
 - https://github.com/element-hq/synapse/issues/16940
 - https://github.com/element-hq/synapse/issues/18182
 - https://github.com/element-hq/synapse/issues/18793
 - https://github.com/element-hq/synapse/issues/19478

---

Docker builds preferring remote image over the local image we just
built,
https://github.com/element-hq/synapse/pull/19460#discussion_r2818080879

`containerd` image store (storage driver, driver type)

-> https://github.com/element-hq/synapse/pull/19475


### Todo

- [x] Wait for https://github.com/element-hq/synapse/pull/19463 to merge
so the Complement tests all pass
- [x] Wait for https://github.com/element-hq/synapse/pull/19475 to merge

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [x] Pull request is based on the develop branch
* [x] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
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.
* [x] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))

---------

Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
2026-03-03 15:13:59 +01:00
Eric EastwoodandAndrew Ferrazzutti b2778dae70 Fix Complement CI not running against the code from our PRs (remote images being chosen over local) (#19475)
Fix remote images being chosen over the local ones we just built with
Complement in CI (any Docker environment using the `containerd` image
store). This problem means that Complement jobs in CI don't actually
test against the code from the PR (since 2026-02-10).

This PR approaches the problem the same way that @AndrewFerr proposed in
https://github.com/element-hq/synapse/pull/18210. This is better than
the alternative listed below as we can just make our code compatible
with whatever image store is being used.
### Problem

Spawning from
https://github.com/element-hq/synapse/pull/19460#discussion_r2818760635
where we found that our Complement jobs in CI don't actually test
against the code from the PR at the moment.

This is caused by a change in Docker Engine 29.0.0:

> `containerd` image store is now the default for **fresh installs**.
This doesn't apply to daemons configured with `userns-remap` (see
[moby#47377](https://github.com/moby/moby/issues/47377)).
>
> *-- 29.0.0 (2025-11-10),
https://docs.docker.com/engine/release-notes/29/#2900*

And our `ubuntu-latest` GitHub runner (`Current runner version:
'2.331.0'`)
[points](https://github.com/actions/runner-images/blob/ubuntu24/20260209.23/images/ubuntu/Ubuntu2404-Readme.md)
to using Docker client/server `29.1.5` 🎯

This Docker version bump happened on
https://github.com/actions/runner-images/commit/416418df15a48321bdf51c3978c07a84a1873c75
(2026-02-10) (`28.0.4` -> `29.1.5`). Specific PR:
https://github.com/actions/runner-images/pull/13633

---

I found this because I reviewed and remembered
https://github.com/element-hq/synapse/pull/18210 was a thing that
@AndrewFerr ran into. And then running `dockers system prune` also
revealed the problematic `containerd` in CI. Checking the Docker
changelogs, I found the new default culprit and then could trace down
where the GitHub runners made the dependency update.

---------

Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
2026-02-18 11:37:09 -06:00
Eric Eastwood 46d235cd52 Add in-repo Complement tests (#19406)
This is useful so we can test Synapse
specific behaviors like our admin API.

(see docs in PR, `complement/README.md`)
```
COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh --in-repo
```

Complement calls these
["out-of-repo"](https://github.com/matrix-org/complement/blob/78c255edcebfcb0ac5e3c86d49d76cb21fdd035a/OUT-OF-REPO-TESTS.md)
tests but it's a bit of a misnomer once they're in your project. (just
depends on the perspective)

There has been [previous
desire](https://github.com/element-hq/synapse/pull/19021#discussion_r2453442191)
for this kind of thing but this is spawning from wanting to have some
tests for our purge history admin API
(https://github.com/element-hq/synapse-rust-apps/issues/430). There are
some Sytest tests ([`matrix-org/sytest` ->
`tests/48admin.pl#L91-L618`](https://github.com/matrix-org/sytest/blob/1be04cce46c0f84abac736390dc3fab17f35a756/tests/48admin.pl#L91-L618))
for this already but I'd much rather work in Complement instead of
Sytest. I'm wanting these tests to ensure that our new `event-cache`
rust app for Synapse Pro doesn't break these kind of erasure features
(https://github.com/element-hq/synapse-rust-apps/issues/366 and
https://github.com/element-hq/synapse-rust-apps/issues/153).

Interestingly, there is already [`matrix-org/complement` ->
`tests/csapi/admin_test.go`](https://github.com/matrix-org/complement/blob/78c255edcebfcb0ac5e3c86d49d76cb21fdd035a/tests/csapi/admin_test.go)
(added in https://github.com/matrix-org/complement/pull/322) in the
Complement repo iteslf that tests the
`/_synapse/admin/v1/send_server_notice` endpoint but it's a bit of an
interesting case as [Dendrite also supports this
endpoint](https://github.com/matrix-org/dendrite/pull/2180). I don't
think it's good practice to continually shove in more and more
Synapse-specific behavior into the Complement repo itself.

We already have success with other out-of-repo tests for projects like
the
[SBG](https://github.com/element-hq/sbg/tree/b76b05b53e40bf6890e51dd1b83cec3460274eb2/complement_tests),
[TI-Messenger
Proxy](https://github.com/element-hq/ti-messenger-proxy/tree/c8fa87feccc743c01cccbbc2685321206b532925/complement),
and our [Synapse Pro for small
hosts](https://github.com/element-hq/synapse-small-hosts/tree/c2ea7eabf3e1d7c26a5312ebef326b254937be99/complement).
2026-02-05 17:11:55 -06:00
Devon Hudson 8b36740bad Fix InFlightGauge typing to allow upgrading to prometheus_client 0.24 (#19379)
Fixes #19375 

`prometheus_client` 0.24 makes `Collector` a generic type. 
Previously, `InFlightGauge` inherited from both `Generic[MetricsEntry]`
and `Collector`, resulting in the error `TypeError: cannot create a
consistent MRO` when using `prometheus_client` >= 0.24. This behaviour
of disallowing multiple `Generic` inheritance is more strictly enforced
starting with python 3.14, but can still lead to issues with earlier
versions of python.

This PR separates runtime and typing inheritance for `InFlightGauge`:
- Runtime: `InFlightGauge` inherits only from `Collector`
- Typing: `InFlightGauge` is generic

This preserves static typing, avoids MRO conflicts, and supports both
`prometheus_client` <0.24 and >=0.24.

I have tested these changes out locally with `prometheus_client` 0.23.1
& 0.24 on python 3.14 while sending a bunch of messages over federation
and watching a grafana dashboard configured to show
`synapse_util_metrics_block_in_flight_total` &
`synapse_util_metrics_block_in_flight_real_time_sum` (the only metric
setup to use `InFlightGauge`) and things are working in each case.
https://github.com/element-hq/synapse/blob/a1e9abc7df3e6c43a95cba059348546a4c9d4491/synapse/util/metrics.py#L112-L119

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [X] Pull request is based on the develop branch
* [X] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
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.
* [X] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))
2026-01-16 20:35:30 +00:00
Andrew Ferrazzutti 079c52e16b MSC4140: delayed event content as text, not bytes (#19360)
Store the JSON content of scheduled delayed events as text instead of a
byte array. This brings it in line with the `event_json` table's `json`
column, and fixes the inability to schedule a delayed event with
non-ASCII characters in its content.

Fixes #19242
2026-01-15 16:05:19 +00:00
Andrew Morgan 9285cdf041 Update usage of deprecated release.title in release script (#19358) 2026-01-13 15:52:01 +00:00
dependabot[bot] 164b980085 Bump the minor-and-patches group with 2 updates (#19339) 2026-01-13 14:25:42 +00:00
Andrew Morgan 1db2302303 Bump mdbook from 0.4.17 -> 0.5.2 and remove custom table-of-contents plugin (#19356) 2026-01-07 18:46:03 +00:00
KierreandAndrew Morgan 7ea78671a3 Drop support for Ubuntu 25.04 'Plucky Puffin', add support for Ubuntu 25.10 'Questing Quokka' (#19348)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
2026-01-07 14:10:25 +00:00
Denis KasakandAndrew Morgan 29fd0116a5 Improve proxy support for the federation_client.py dev script (#19300)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
2025-12-16 11:06:07 +00:00
Erik JohnstonandEric Eastwood dfd00a986f Fix sliding sync performance slow down for long lived connections. (#19206)
Fixes https://github.com/element-hq/synapse/issues/19175

This PR moves tracking of what lazy loaded membership we've sent to each
room out of the required state table. This avoids that table from
continuously growing, which massively helps performance as we pull out
all matching rows for the connection when we receive a request.

The new table is only read when we have data in a room to send, so we
end up reading a lot fewer rows from the DB. Though we now read from
that table for every room we have events to return in, rather than once
at the start of the request.

For an explanation of how the new table works, see the
[comment](https://github.com/element-hq/synapse/blob/erikj/sss_better_membership_storage2/synapse/storage/schema/main/delta/93/02_sliding_sync_members.sql#L15-L38)
on the table schema.

The table is designed so that we can later prune old entries if we wish,
but that is not implemented in this PR.

Reviewable commit-by-commit.

---------

Co-authored-by: Eric Eastwood <erice@element.io>
2025-12-12 10:02:57 +00:00
Andrew Morgan 0dfc21ca9f Remove "Updates to locked dependencies" section from changelog (#19254) 2025-12-02 16:45:41 +00:00
Devon HudsonandOlivier 'reivilibre' d435cfc125 Add mention of future deprecations to release script (#19239)
Small improvement to the release script to prompt the user to consider
upcoming deprecations that should be mentioned in the changelog.

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [X] Pull request is based on the develop branch
* [X] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
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.
* [X] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))

---------

Co-authored-by: Olivier 'reivilibre' <oliverw@element.io>
2025-12-01 15:47:36 +00:00
Erik Johnston 78ec3043d6 Use sqlglot to properly check SQL delta files (#19224)
Rather than using dodgy regexes which keep breaking.

Also fixes a regression where it looks like we didn't fail CI if the
delta was in the wrong place.
2025-11-28 15:49:15 +00:00
Eric Eastwood 54c93a1372 Export SYNAPSE_SUPPORTED_COMPLEMENT_TEST_PACKAGES from scripts-dev/complement.sh (#19208)
This is useful as someone downstream can source the
`scripts-dev/complement.sh` script and run the same set of tests as
Synapse:

```bash
# Grab the test packages supported by Synapse.
#
# --fast: Skip rebuilding the docker images,
# --build-only: Will only build Docker images but because we also used `--fast`, it won't do anything.
# `>/dev/null` to redirect stdout to `/dev/null` to get rid of the `echo` logs from the script.
test_packages=$(source ${SYNAPSE_DIR}/scripts-dev/complement.sh --fast --build-only >/dev/null && echo "$SYNAPSE_SUPPORTED_COMPLEMENT_TEST_PACKAGES")
echo $test_packages
```

This is spawning from wanting to run the same set of Complement tests in
the https://github.com/element-hq/synapse-rust-apps project.
2025-11-21 19:01:43 -06:00
Eric Eastwood e39fba61a7 Refactor scripts-dev/complement.sh logic to avoid exit (#19209)
This is useful so that the script can be sourced by other scripts
without exiting the calling subshell (composable).

This is split out from https://github.com/element-hq/synapse/pull/19208
to make easy to understand PR's and build up to where we want to go.
2025-11-21 10:51:19 -06:00
Andrew Ferrazzutti fcac7e0282 Write union types as X | Y where possible (#19111)
aka PEP 604, added in Python 3.10
2025-11-06 14:02:33 -06:00
Erik Johnston 3ccc5184e0 Fix schema lint script to understand CREATE TABLE IF NOT EXISTS (#19020)
The schema lint tries to make sure we don't add or remove indices in
schema files (rather than as background updates), *unless* the table was
created in the same schema file.

The regex to pull out the `CREATE TABLE` SQL incorrectly didn't
recognise `IF NOT EXISTS`.

There is a test delta file that shows that we accept different types of
`CREATE TABLE` and `CREATE INDEX` statements, as well as an index
creation that doesn't have a matching create table (to show that we do
still catch it). The test delta should be removed before merge.
2025-10-31 13:16:47 +00:00
3595ff921f Pydantic v2 (#19071)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
Co-authored-by: Andrew Morgan <andrew@amorgan.xyz>
2025-10-31 09:22:22 +00:00
Andrew Ferrazzutti e0838c2567 Drop Python 3.9, bump tests/builds to Python 3.10 (#19099)
Python 3.9 EOL is on 2025-10-31
2025-10-29 12:15:00 -05:00
Andrew Morgan 7897c8f6af Add a docs page with common steps to review the release notes (#19109) 2025-10-29 11:32:33 +00:00
Andrew Morgan a092d2053a Fix deprecation warning in release script (#19080) 2025-10-24 11:19:04 +01:00
Andrew Morgan 5556b491c1 Spruce up generated announcement text in the release script (#19089) 2025-10-24 10:19:44 +01:00
Andrew Ferrazzutti fc244bb592 Use type hinting generics in standard collections (#19046)
aka PEP 585, added in Python 3.9

 - https://peps.python.org/pep-0585/
 - https://docs.astral.sh/ruff/rules/non-pep585-annotation/
2025-10-22 16:48:19 -05:00