Now it also passes CI
On Thu, Oct 8, 2026 at 11:35 AM Hannu Krosing <hannuk(at)google(dot)com> wrote:
>
> Hi hackers,
>
> One of the persistent challenges for connection poolers (PgBouncer, pgpool-II,
> Odyssey) and connection routers in transaction-pooling mode is determining
> whether a backend connection is clean enough to be safely recycled back into
> the pool without issuing expensive round-trip cleanup probes (such as
> DISCARD ALL,
> querying pg_prepared_xacts, or checking for active WITH HOLD cursors
> or temporary
> namespaces).
>
> Similarly, with the introduction of replication wait commands (such as
> WAIT FOR LSN / pg_wal_replay_wait()), proxies and clients wishing to achieve
> causal consistency (read-your-own-writes across read replicas) need to know
> the commit LSN of the transaction just completed on the primary backend without
> incurring the round-trip overhead of an extra SELECT
> pg_current_wal_insert_lsn().
>
> To address this, the attached patch introduces an extensible ReadyForQuery ('Z')
> frontend/backend wire protocol message format and a corresponding C hook
> (ready_for_query_hook).
>
> Key highlights:
>
> 1. GUC Parameter: ready_for_query_message
> - Enum with values 'plain' (default) and 'rich'.
> - Context PGC_USERSET with GUC_REPORT.
> - When 'plain', the protocol message is completely unchanged (5-byte length).
> - When 'rich', the message length header is expanded to include additional
> length-prefixed key-value pairs:
> [uint8 key_len][key_bytes][uint8 val_len][val_bytes].
>
> QUESTION: do we want a more detailed setting, like
> SET ready_for_query_message = "rich:THL"
> to sent only these three?
>
> 2. Built-in Session State Indicators (in 'rich' mode):
> - 'T': "1" if temporary tables/schemas are active, "0" otherwise
> (O(1) check).
> - 'H': "1" if active WITH HOLD cursors exist in the session, "0" otherwise.
> - 'P': "1" if active 2PC prepared transactions exist, "0" otherwise.
> - 'L': Last transaction commit LSN as text (from XactLastCommitEnd).
>
> 3. C Hook: ready_for_query_hook
> - Declared as: typedef void (*ready_for_query_hook_type) (StringInfo buf);
> - Extensions can register this hook and use ready_for_query_has_key()
> and ready_for_query_append_kv() to add custom contextual metadata
> (e.g., custom session flags, tenant tags, or replication state).
>
> 4. Protocol Compatibility:
> - Unless you set ready_for_query_message=rich the protocol does not
> change at all
> - libpq (fe-protocol3.c) is updated so that clients ignore any trailing
> extension bytes in ReadyForQuery messages if they receive them, ensuring
> full forward and backward compatibility.
>
> 5. Tests & Documentation:
> - Documentation added in doc/src/sgml/protocol.sgml and
> doc/src/sgml/config.sgml.
> - Test module src/test/modules/test_ready_for_query includes both
> SQL regression
> and TAP test suites validating standard/rich modes, startup options,
> temp tables, cursors, 2PC, LSN, and hook injection.
>
> The patch applies cleanly against current master. Feedback and suggestions are
> welcome.
>
> Regards,
> Hannu Krosing