Bugfix: standby cluster switchover (#2900)

1.  Enforce `_load_cluster()` after acquisition for the leader lock in ZooKeeper. Sometimes the notification from ZooKeeper was arriving too late and Patroni wasn't setting the `role=standby_leader`.

2. The `_get_node_to_follow()` method was falsely assuming that we still own the leader lock and returning the remote node instead of the new standby leader. While not a big issue per se, because the next HA loop usually fixes it, such behavior was causing flakiness of behave tests with Postgres 12 and older, where restart is required to update `primary_conninfo` GUC.
This commit is contained in:
Alexander Kukushkin
2023-10-10 12:21:19 +02:00
committed by GitHub
parent 9b8c40a6e1
commit 535dc631ec
2 changed files with 4 additions and 1 deletions
+1
View File
@@ -334,6 +334,7 @@ class ZooKeeper(AbstractDCS):
try:
self._client.retry(self._client.create, self.leader_path, self._name.encode('utf-8'),
makepath=True, ephemeral=True)
self.cluster_watcher(None) # the next _load_cluster() call must read from ZooKeeper.
return True
except (ConnectionClosedError, RetryFailedError) as e:
raise ZooKeeperError(e)
+3 -1
View File
@@ -584,7 +584,9 @@ class Ha(object):
"""
# The standby leader or when there is no standby leader we want to follow
# the remote member, except when there is no standby leader in pause.
if self.is_standby_cluster() and (self.has_lock(False) or self.cluster.is_unlocked() and not self.is_paused()):
if self.is_standby_cluster() \
and (cluster.leader and cluster.leader.name and cluster.leader.name == self.state_handler.name
or cluster.is_unlocked() and not self.is_paused()):
node_to_follow = self.get_remote_member()
# If replicatefrom tag is set, try to follow the node mentioned there, otherwise, follow the leader.
elif self.patroni.replicatefrom and self.patroni.replicatefrom != self.state_handler.name: