mirror of
https://github.com/element-hq/synapse.git
synced 2026-11-04 13:28:04 +00:00
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