mirror of
https://github.com/element-hq/synapse.git
synced 2026-08-15 02:40:29 +00:00
Model the lifecycle of a cursor's most recent query as an explicit state machine (Idle / Active / Closed) so that illegal field combinations are unrepresentable and fetching past the end of a result set is a clean, specific error rather than the spurious "connection closed" you get from re-polling a finished stream. The row stream is fused so an exhausted-but-not-yet-reported stream can sit safely in `Active`. This change adds `fetch_one`, `fetch_all` and `rowcount` (the batched `fetch_next_batch` follows separately). On a stream error a cursor resets to `Idle`; on normal exhaustion it moves to `Closed`, retaining the PEP-249 rowcount from the command tag. The state machine is generic over the stream type, defaulting to `RowStream`, via a small `CursorRowStream` trait that abstracts the three things the logic needs (the affected-row count, row->PyTuple conversion, and error rendering). This is what lets the state transitions, exhaustion handling and error recovery be unit-tested against an in-memory fake stream, with no live Postgres server. `cursor_state` is `pub` for now so its not-yet-consumed items don't trip clippy's dead_code lint; the connection code wires it up and tightens that later. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>