jackc / pgx

PostgreSQL driver and toolkit for Go
MIT License
10.83k stars 845 forks source link

Connection timeout wrongly applied to non-preferred hosts #2172

Open jwreschnig-utiq opened 23 hours ago

jwreschnig-utiq commented 23 hours ago

Describe the bug (Related to the testing I mentioned #2171 but this appears to be a straightforward bug.)

When connecting with a target_session_attrs preference that cannot be satisfied and the final host times out, the connection to the non-preferred host is not attempted and falsely times out.

To Reproduce

  1. Create a connection string with two hosts and a preference for the second; e.g. a primary and standby with target_session_attrs=prefer-standby
  2. Block network traffic from the client to the standby.
  3. Configure a connection timeout for e.g. 1 second.
  4. Execute a query.

Expected behavior After 1 second the connection to the standby times out, the primary is chosen instead, and the query executes.

Actual behavior After 1 second the query returns a timeout.

Version

Additional context From my understanding of the code, connectPreferred resets the timeout for each new host as it iterates the possible targets. However, once it's decided to fall back to fallbackConnectOneConfig, it reuses whatever the last ctx it had from the initial pass was. If this had timed out, the new connection will start in a timed-out state. It should instead probably iterate the entire list again with fresh contexts based on octx. Or, as an optimization, the first non-preferred connection could be returned rather than the config and returned directly if no other preferred one is found / closed if a preferred one is found.