Skip to content

feat: add proxy topology mode for SPQR-compatible routing - #33

Open
Denchick wants to merge 1 commit into
gravity-ui:mainfrom
Denchick:feat/proxy-topology-mode
Open

feat: add proxy topology mode for SPQR-compatible routing#33
Denchick wants to merge 1 commit into
gravity-ui:mainfrom
Denchick:feat/proxy-topology-mode

Conversation

@Denchick

Copy link
Copy Markdown

Problem

PostgresKit currently assumes that every connection string represents an individual node in a PostgreSQL primary/replica cluster.

To determine each node's role, it periodically executes:

SELECT pg_is_in_recovery();

A false result identifies a primary, while true identifies a replica.

This assumption does not work for SPQR. The supplied endpoints represent equivalent SPQR router instances rather than individual PostgreSQL nodes. A router can accept both read and write queries and forward them to the appropriate backend.

SPQR routers report themselves as primary for pg_is_in_recovery(). Therefore, when several router endpoints are configured, PostgresKit classifies all of them as primaries and may report:

Multiple primary connections detected, something is wrong

or:

No alive replica available, using master for read

Having multiple endpoints classified as “masters” is normal for an SPQR deployment: these are equivalent router instances, not multiple writable PostgreSQL primary nodes. The warnings are produced by PostgresKit because its primary/replica topology model does not match the actual SPQR topology.

Suppressing status logs does not solve the problem because it only hides the warnings while leaving the incorrect routing model in place.

Solution

This PR adds an optional dispatcher topology mode:

initDB({
  connectionString: process.env.POSTGRES_DSN_LIST,
  dispatcherOptions: {
    topologyMode: 'proxy',
  },
});

In proxy mode, PostgresKit:

  • uses SELECT 1 instead of pg_is_in_recovery() for health checks;
  • treats every healthy endpoint as eligible for both db.primary and db.replica;
  • selects the healthy endpoint with the lowest latest health-check latency;
  • excludes unhealthy endpoints;
  • does not produce primary/replica topology warnings;
  • preserves the existing unavailable-database error when no healthy endpoints remain.

Backward compatibility

primary-replica remains the default topology mode. When topologyMode is omitted, the existing health checks, routing behavior, warnings, and errors remain unchanged.

Testing

Added tests covering:

  • existing primary/replica behavior in the default mode;
  • role-agnostic proxy health checks;
  • fastest healthy proxy selection for both db.primary and db.replica;
  • unhealthy endpoint exclusion;
  • behavior when all proxy endpoints are unavailable;
  • absence of primary/replica topology warnings in proxy mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant