Files
synapse/rust
Erik JohnstonandClaude Opus 5.5 61b80bd003 Queue writes in a Rust write transaction and send them together
A `WriteTxn` sent each statement and waited for it before the next, so
a transaction of forty writes took forty round trips, though nothing
read most of their results.

Writes can now be queued with `execute_later`, `insert_many_later` and
`upsert_many_later`, which take owned parameters. Every statement that is
not queued, and the `COMMIT`, first sends the queued writes, in order,
in the same round trip: tokio-postgres sends a request when its future is
first polled, and `join_in_order` polls them in order. So no read can
overtake a queued write, and a transaction ending in queued writes sends
them with its `COMMIT`. Statements not yet prepared on the connection
are prepared together first.

tokio-postgres encodes a request's parameters on its first poll and sends
nothing if that fails, while later requests still go out. So the queued
writes' parameters are checked against their prepared statements' types
before any is sent: otherwise the writes after a bad one, and the COMMIT,
would go through. A dry run sends its queue before rolling back, so it
still checks the writes. The statement methods must not run
concurrently, or a statement could overtake writes queued before it.

A queued write that fails surfaces at the next statement, reported as
its own failure (with an optional mapping, for callers that turn a
constraint violation into a domain error), rather than as the "current
transaction is aborted" error of the statements after it. A failed
attempt drops its queue unsent.

`execute_batch` uses `join_in_order` too: `try_join_all` does not promise
to poll long lists in order.

Nothing queues writes yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVLsNh6akt4ifEizY4D1ta
2026-10-18 20:12:22 +00:00
..