[PATCH] Extensible ReadyForQuery wire protocol message and C hook, for connection pools and WAIT FOR LSN - Mailing list pgsql-hackers

From Hannu Krosing
Subject [PATCH] Extensible ReadyForQuery wire protocol message and C hook, for connection pools and WAIT FOR LSN
Date
Msg-id CAMT0RQSP2Qopgr+5Z5NH1wur17=2fs0VAn5v3F8TtyQEApCmAQ@mail.gmail.com
Whole thread
Responses Re: [PATCH] Extensible ReadyForQuery wire protocol message and C hook, for connection pools and WAIT FOR LSN
List pgsql-hackers
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

Attachment

pgsql-hackers by date:

Previous
From: Manu
Date:
Subject: Re: Add a hint to the "WAL summaries are required" errors
Next
From: Osama Abdul Qader
Date:
Subject: Re: Regress test might fail due to deadlock between domain and alter_table