mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
Refactor REST API health-checks (#779)
Make it more readable and easy to understand. Mostly it is needed to implement https://github.com/zalando/patroni/issues/772
This commit is contained in:
+13
-28
@@ -84,35 +84,20 @@ class RestApiHandler(BaseHTTPRequestHandler):
|
||||
patroni = self.server.patroni
|
||||
cluster = patroni.dcs.cluster
|
||||
|
||||
def is_synchronous():
|
||||
return (cluster.is_synchronous_mode() and cluster.sync
|
||||
and cluster.sync.sync_standby == patroni.postgresql.name)
|
||||
replica_status_code = 200 if not patroni.noloadbalance and response.get('role') == 'replica' else 503
|
||||
status_code = 503
|
||||
|
||||
def is_balanceable_replica():
|
||||
return response.get('role') == 'replica' and not patroni.noloadbalance
|
||||
|
||||
if cluster: # dcs available
|
||||
if patroni.ha.is_leader():
|
||||
status_code = 200 if 'master' in path else 503
|
||||
elif 'role' not in response:
|
||||
status_code = 503
|
||||
elif response['role'] == 'master': # running as master but without leader lock!!!!
|
||||
status_code = 503
|
||||
elif path in ('/sync', '/synchronous'):
|
||||
status_code = 200 if is_balanceable_replica() and is_synchronous() else 503
|
||||
elif path in ('/async', '/asynchronous'):
|
||||
status_code = 200 if is_balanceable_replica() and not is_synchronous() else 503
|
||||
elif response['role'] in path: # response['role'] != 'master'
|
||||
status_code = 503 if patroni.noloadbalance else 200
|
||||
else:
|
||||
status_code = 503
|
||||
elif 'role' in response and response['role'] in path:
|
||||
status_code = 503 if response['role'] != 'master' and patroni.noloadbalance else 200
|
||||
elif patroni.ha.restart_scheduled() and patroni.postgresql.role == 'master' and 'master' in path:
|
||||
# exceptional case for master node when the postgres is being restarted via API
|
||||
status_code = 200
|
||||
else:
|
||||
status_code = 503
|
||||
if 'master' in path:
|
||||
status_code = 200 if patroni.ha.is_leader() else 503
|
||||
elif 'replica' in path:
|
||||
status_code = replica_status_code
|
||||
elif cluster: # dcs is available
|
||||
is_synchronous = cluster.is_synchronous_mode() and cluster.sync \
|
||||
and cluster.sync.sync_standby == patroni.postgresql.name
|
||||
if path in ('/sync', '/synchronous') and is_synchronous:
|
||||
status_code = replica_status_code
|
||||
elif path in ('/async', '/asynchronous') and not is_synchronous:
|
||||
status_code = replica_status_code
|
||||
|
||||
if write_status_code_only: # when haproxy sends OPTIONS request it reads only status code and nothing more
|
||||
message = self.responses[status_code][0]
|
||||
|
||||
@@ -155,6 +155,7 @@ class TestRestApiHandler(unittest.TestCase):
|
||||
with patch.object(RestApiHandler, 'get_postgresql_status', Mock(return_value={'role': 'replica'})):
|
||||
MockRestApiServer(RestApiHandler, 'GET /synchronous')
|
||||
with patch.object(RestApiHandler, 'get_postgresql_status', Mock(return_value={'role': 'replica'})):
|
||||
MockPatroni.dcs.cluster.sync.sync_standby = ''
|
||||
MockRestApiServer(RestApiHandler, 'GET /asynchronous')
|
||||
MockPatroni.ha.is_leader = Mock(return_value=True)
|
||||
MockRestApiServer(RestApiHandler, 'GET /replica')
|
||||
|
||||
Reference in New Issue
Block a user