Skip to content

fix(config): accept multi-host PostgreSQL URLs - #2387

Open
A-RYAN-1 wants to merge 1 commit into
tortoise:developfrom
A-RYAN-1:fix/1924-multi-host-postgres-dsn
Open

A-RYAN-1 wants to merge 1 commit into
tortoise:developfrom
A-RYAN-1:fix/1924-multi-host-postgres-dsn

Conversation

@A-RYAN-1

Copy link
Copy Markdown

Description

Accept libpq style multi-host PostgreSQL URLs, postgres://user:pass@host1:5432,host2:5433/db?target_session_attrs=read-write, for the postgres, postgresql, asyncpg and psycopg schemes. The host part is split on commas, each entry takes its own optional port, and a bare host takes the port from the query string or 5432. A single-host URL gives exactly the same result as before. When a URL lists several hosts, a ?host= value in its query string is ignored.

The clients take the lists as they are for asyncpg, and psycopg joins them with commas for libpq. psycopg also reads target_session_attrs from the URL, which asyncpg already accepted through its connect arguments, so the example above works with both drivers.

Motivation and Context

Fixes #1924. urlparse returns host1,host2 as one hostname, so asyncpg tried to resolve it as a single DNS name and failed with socket.gaierror. psycopg already worked for a shared port (libpq splits the string itself) but not for per-host ports. The closed attempt in #2267 split hosts for asyncpg only; this also covers per-host ports, IPv6 literals, psycopg and the target_session_attrs parameter from the issue's own URL.

How Has This Been Tested?

  • New tests in tests/backends/test_db_url.py (shared port, per-host ports, query parameters, IPv6, the query port as default, invalid port and empty host, other schemes unchanged) and tests/backends/test_connection_params.py (the host and port lists reach asyncpg, the joined strings reach psycopg's conninfo, single-host types stay str and int). Twelve of them fail on develop and all pass with the change.
  • tests/backends on Linux against PostgreSQL 17: 93 passed, 6 skipped, 1 xfailed.
  • Against a real server with a dead first host (host:54399,host:54320), with and without ?target_session_attrs=read-write: asyncpg and psycopg both connect to the second host on Linux. On Windows, psycopg's own connection pool fails the same way with a dead first host outside Tortoise, so that case was not used there.
  • mypy tortoise/backends is clean and ruff reports nothing new on the touched files.

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added the changelog accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

A URL such as postgres://u:p@host1,host2:5432/db is libpq's failover
syntax. urlparse reads "host1,host2" back as one hostname, so asyncpg
tried to resolve it as a single DNS name and failed.

Split the host part of postgres, postgresql, asyncpg and psycopg URLs
on commas, each entry with its own optional port (a bare host takes the
port of the query string or 5432), and pass lists to the clients.
asyncpg takes the lists as they are; psycopg gets the comma joined
strings libpq expects. psycopg also reads target_session_attrs from the
URL query, as asyncpg already did through its connect arguments.

Single-host URLs are unchanged.

Fixes tortoise#1924
@codspeed

codspeed Bot commented Oct 29, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

1 warning

⚠️ 21 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

✅ 24 untouched benchmarks


Comparing A-RYAN-1:fix/1924-multi-host-postgres-dsn (185be6d) with develop (7b43710)

Open in CodSpeed

This branch has not been deployed

No deployments
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.

Postgres connection string (dsn) with multi-host does not work

1 participant