From 55e1549341b2aa62c09fcded1bf4b8e617452da5 Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Thu, 29 Dec 2022 09:13:09 +0100 Subject: [PATCH] Do not rely on 'role' value when checking other nodes via REST API (#2503) When doing the leader race we need to check that the former primary isn't alive anymore. For that we relied on non-inclusive terms. In order to simplify future work on getting rid from all non-inclusive words we change the check to rely on a difference in format of wal/xlog field. There is only "location" for the primary and "replayed_location" + "received_location" for standbys. In addition to that we start supporting "wal" field as well as deprecated "xlog". Co-authored-by: Polina Bungina --- patroni/ha.py | 15 ++++++++++++--- tests/__init__.py | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/patroni/ha.py b/patroni/ha.py index 03f31d87..6c4e3e97 100644 --- a/patroni/ha.py +++ b/patroni/ha.py @@ -39,11 +39,20 @@ class _MemberStatus(namedtuple('_MemberStatus', ['member', 'reachable', 'in_reco """ @classmethod def from_api_response(cls, member, json): - is_master = json['role'] == 'master' + """ + :param member: dcs.Member object + :param json: RestApiHandler.get_postgresql_status() result + :returns: _MemberStatus object + """ + # If one of those is not in a response we want to count the node as not healthy/reachable + assert 'wal' in json or 'xlog' in json + + wal = json.get('wal', json.get('xlog')) + in_recovery = not bool(wal.get('location')) # abuse difference in primary/replica response format timeline = json.get('timeline', 0) dcs_last_seen = json.get('dcs_last_seen', 0) - wal = not is_master and max(json['xlog'].get('received_location', 0), json['xlog'].get('replayed_location', 0)) - return cls(member, True, not is_master, dcs_last_seen, timeline, wal, + wal = in_recovery and max(wal.get('received_location', 0), wal.get('replayed_location', 0)) + return cls(member, True, in_recovery, dcs_last_seen, timeline, wal, json.get('tags', {}), json.get('watchdog_failed', False)) @classmethod diff --git a/tests/__init__.py b/tests/__init__.py index 9daea2dc..0c634828 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -50,7 +50,7 @@ def requests_get(url, **kwargs): if url.startswith('http://local'): raise urllib3.exceptions.HTTPError() elif ':8011/patroni' in url: - response.content = '{"role": "replica", "xlog": {"received_location": 0}, "tags": {}}' + response.content = '{"role": "replica", "wal": {"received_location": 0}, "tags": {}}' elif url.endswith('/members'): response.content = '[{}]' if url.startswith('http://error') else members elif url.startswith('http://exhibitor'):