Fix timeout when underlying socket is changed in a MultiConnection (#7377)

When there are multiple localhost entries in /etc/hosts like following
/etc/hosts:
```
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1   localhost
```

multi_cluster_management check will failed:
```

@@ -857,20 +857,21 @@
 ERROR:  group 14 already has a primary node
 -- check that you can add secondaries and unavailable nodes to a group
 SELECT groupid AS worker_2_group FROM pg_dist_node WHERE nodeport = :worker_2_port \gset
 SELECT 1 FROM master_add_node('localhost', 9998, groupid => :worker_1_group, noderole => 'secondary');
  ?column?
 ----------
         1
 (1 row)

 SELECT 1 FROM master_add_node('localhost', 9997, groupid => :worker_1_group, noderole => 'unavailable');
+WARNING:  could not establish connection after 5000 ms
  ?column?
 ----------
         1
 (1 row)
```

This actually isn't just a problem in test environments, but could occur
as well during actual usage when a hostname in pg_dist_node
resolves to multiple IPs and one of those IPs is unreachable.
Postgres will then automatically continue with the next IP, but
Citus should listen for events on the new socket. Not on the
old one.

Co-authored-by: chuhx43211 <chuhx43211@hundsun.com>
pull/7379/head
LightDB Enterprise Postgres 2024-01-10 18:49:53 +08:00 committed by GitHub
parent 8e979f7ac6
commit 9a91136a3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 8 additions and 1 deletions

View File

@ -1046,8 +1046,15 @@ FinishConnectionListEstablishment(List *multiConnectionList)
continue; continue;
} }
bool beforePollSocket = PQsocket(connectionState->connection->pgConn);
bool connectionStateChanged = MultiConnectionStatePoll(connectionState); bool connectionStateChanged = MultiConnectionStatePoll(connectionState);
if (beforePollSocket != PQsocket(connectionState->connection->pgConn))
{
/* rebuild the wait events if MultiConnectionStatePoll() changed the socket */
waitEventSetRebuild = true;
}
if (connectionStateChanged) if (connectionStateChanged)
{ {
if (connectionState->phase != MULTI_CONNECTION_PHASE_CONNECTING) if (connectionState->phase != MULTI_CONNECTION_PHASE_CONNECTING)