Skip to content

Commit 07b81cd

Browse files
hughcapetavandras
authored andcommitted
Convert states to enums (patroni#3293)
- Postgresql._state - pg_isready state
1 parent b47d7b9 commit 07b81cd

23 files changed

+180
-174
lines changed

patroni/api.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from .__main__ import Patroni
3131
from .dcs import Cluster
3232
from .exceptions import PostgresConnectionException, PostgresException
33-
from .postgresql.misc import postgres_version_to_int, PostgresqlRole, PostgresqlState
33+
from .postgresql.misc import postgres_version_to_int, PostgresqlState
3434
from .utils import cluster_as_json, deep_compare, enable_keepalive, parse_bool, \
3535
parse_int, patch_config, Retry, RetryFailedError, split_host_port, tzutc, uri
3636

@@ -323,7 +323,7 @@ def do_GET(self, write_status_code_only: bool = False) -> None:
323323
is_lagging = leader_optime and leader_optime > replayed_location + max_replica_lag
324324

325325
replica_status_code = 200 if not patroni.noloadbalance and not is_lagging and \
326-
response.get('role') == PostgresqlRole.REPLICA and response.get('state') == PostgresqlState.RUNNING else 503
326+
response.get('role') == 'replica' and response.get('state') == PostgresqlState.RUNNING else 503
327327

328328
if not cluster and response.get('pause'):
329329
leader_status_code = 200 if response.get('role') in (PostgresqlRole.PRIMARY,
@@ -359,7 +359,7 @@ def do_GET(self, write_status_code_only: bool = False) -> None:
359359
elif 'read-only' in path and 'sync' not in path and 'quorum' not in path:
360360
status_code = 200 if 200 in (primary_status_code, standby_leader_status_code) else replica_status_code
361361
elif 'health' in path:
362-
status_code = 200 if response.get('state') == 'running' else 503
362+
status_code = 200 if response.get('state') == PostgresqlState.RUNNING else 503
363363
elif cluster: # dcs is available
364364
is_quorum = response.get('quorum_standby')
365365
is_synchronous = response.get('sync_standby')
@@ -463,7 +463,7 @@ def do_GET_readiness(self) -> None:
463463
patroni = self.server.patroni
464464
if patroni.ha.is_leader():
465465
status_code = 200
466-
elif patroni.postgresql.state == 'running':
466+
elif patroni.postgresql.state == PostgresqlState.RUNNING:
467467
status_code = 200 if patroni.dcs.cluster else 503
468468
else:
469469
status_code = 503
@@ -573,7 +573,8 @@ def do_GET_metrics(self) -> None:
573573

574574
metrics.append("# HELP patroni_postgres_running Value is 1 if Postgres is running, 0 otherwise.")
575575
metrics.append("# TYPE patroni_postgres_running gauge")
576-
metrics.append("patroni_postgres_running{0} {1}".format(labels, int(postgres['state'] == 'running')))
576+
metrics.append("patroni_postgres_running{0} {1}".format(
577+
labels, int(postgres['state'] == PostgresqlState.RUNNING)))
577578

578579
metrics.append("# HELP patroni_postmaster_start_time Epoch seconds since Postgres started.")
579580
metrics.append("# TYPE patroni_postmaster_start_time gauge")
@@ -899,7 +900,7 @@ def do_POST_restart(self) -> None:
899900
If it's not able to parse the request body, then the request is silently discarded.
900901
"""
901902
status_code = 500
902-
data = 'restart failed'
903+
data = PostgresqlState.RESTART_FAILED
903904
request = self._read_json_content(body_is_optional=True)
904905
cluster = self.server.patroni.dcs.get_cluster()
905906
if request is None:
@@ -1297,10 +1298,7 @@ def get_postgresql_status(self, retry: bool = False) -> Dict[str, Any]:
12971298
12981299
:returns: a dict with the status of Postgres/Patroni. The keys are:
12991300
1300-
* ``state``: Postgres state among ``stopping``, ``stopped``, ``stop failed``, ``crashed``, ``running``,
1301-
``starting``, ``start failed``, ``restarting``, ``restart failed``, ``initializing new cluster``,
1302-
``initdb failed``, ``running custom bootstrap script``, ``custom bootstrap failed``,
1303-
``creating replica``, or ``unknown``;
1301+
* ``state``: one of :class:`~patroni.postgresql.misc.PostgresqlState` or ``unknown``;
13041302
* ``postmaster_start_time``: ``pg_postmaster_start_time()``;
13051303
* ``role``: :class:`~patroni.postgresql.misc.PostgresqlRole.REPLICA` or
13061304
:class:`~patroni.postgresql.misc.PostgresqlRole.PRIMARY` based on ``pg_is_in_recovery()`` output;
@@ -1342,7 +1340,8 @@ def get_postgresql_status(self, retry: bool = False) -> Dict[str, Any]:
13421340
config = global_config.from_cluster(cluster)
13431341
try:
13441342

1345-
if postgresql.state not in ('running', 'restarting', 'starting'):
1343+
if postgresql.state not in (PostgresqlState.RUNNING, PostgresqlState.RESTARTING,
1344+
PostgresqlState.STARTING):
13461345
raise RetryFailedError('')
13471346
replication_state = ('(pg_catalog.pg_stat_get_wal_receiver()).status'
13481347
if postgresql.major_version >= 90600 else 'NULL') + ", " +\
@@ -1393,7 +1392,7 @@ def get_postgresql_status(self, retry: bool = False) -> Dict[str, Any]:
13931392

13941393
except (psycopg.Error, RetryFailedError, PostgresConnectionException):
13951394
state = postgresql.state
1396-
if state == 'running':
1395+
if state == PostgresqlState.RUNNING:
13971396
logger.exception('get_postgresql_status')
13981397
state = 'unknown'
13991398
result: Dict[str, Any] = {'state': state, 'role': postgresql.role}

patroni/ctl.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
from .config import Config
6666
from .dcs import AbstractDCS, Cluster, get_dcs as _get_dcs, Member
6767
from .exceptions import PatroniException
68-
from .postgresql.misc import postgres_version_to_int, PostgresqlRole, PostgresqlState
68+
from .postgresql.misc import postgres_version_to_int, PostgresqlState
6969
from .postgresql.mpp import get_mpp
7070
from .request import PatroniRequest
7171
from .utils import cluster_as_json, patch_config, polling_loop
@@ -1236,7 +1236,7 @@ def reinit(cluster_name: str, group: Optional[int], member_names: List[str], for
12361236
time.sleep(2)
12371237
for member in wait_on_members:
12381238
data = json.loads(request_patroni(member, 'get', 'patroni').data.decode('utf-8'))
1239-
if data.get('state') != 'creating replica':
1239+
if data.get('state') != PostgresqlState.CREATING_REPLICA:
12401240
click.echo('Reinitialize is completed on: {0}'.format(member.name))
12411241
wait_on_members.remove(member)
12421242

@@ -1746,10 +1746,7 @@ def output_members(cluster: Cluster, name: str, extended: bool = False,
17461746
* ``Member``: name of the Patroni node, as per ``name`` configuration;
17471747
* ``Host``: hostname (or IP) and port, as per ``postgresql.listen`` configuration;
17481748
* ``Role``: ``Leader``, ``Standby Leader``, ``Sync Standby`` or ``Replica``;
1749-
* ``State``: ``stopping``, ``stopped``, ``stop failed``, ``crashed``, ``running``, ``starting``,
1750-
``start failed``, ``restarting``, ``restart failed``, ``initializing new cluster``, ``initdb failed``,
1751-
``running custom bootstrap script``, ``custom bootstrap failed``, ``creating replica``, ``streaming``,
1752-
``in archive recovery``, and so on;
1749+
* ``State``: one of :class:`~patroni.postgresql.misc.PostgresqlState`;
17531750
* ``TL``: current timeline in Postgres;
17541751
``Lag in MB``: replication lag.
17551752

patroni/dcs/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,10 @@ def state(self) -> str:
296296

297297
@property
298298
def is_running(self) -> bool:
299-
"""``True`` if the member :attr:`~Member.state` is ``running``."""
300-
return self.state == 'running'
299+
"""``True`` if the member :attr:`~Member.state` is :class:`~patroni.postgresql.misc.PostgresqlState.RUNNING`."""
300+
from ..postgresql.misc import PostgresqlState
301+
302+
return self.state == PostgresqlState.RUNNING
301303

302304
@property
303305
def patroni_version(self) -> Optional[Tuple[int, ...]]:

patroni/dcs/consul.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from urllib3.exceptions import HTTPError
2020

2121
from ..exceptions import DCSError
22-
from ..postgresql.misc import PostgresqlRole, PostgresqlState
22+
from ..postgresql.misc import PostgresqlState
2323
from ..postgresql.mpp import AbstractMPP
2424
from ..utils import deep_compare, parse_bool, Retry, RetryFailedError, split_host_port, uri, USER_AGENT
2525
from . import AbstractDCS, catch_return_false_exception, Cluster, ClusterConfig, \
@@ -547,12 +547,12 @@ def _update_service(self, data: Dict[str, Any]) -> Optional[bool]:
547547
'enable_tag_override': True,
548548
}
549549

550-
if state == 'stopped' or (not self._register_service and self._previous_loop_register_service):
550+
if state == PostgresqlState.STOPPED or (not self._register_service and self._previous_loop_register_service):
551551
self._previous_loop_register_service = self._register_service
552552
return self.deregister_service(params['service_id'])
553553

554554
self._previous_loop_register_service = self._register_service
555-
if data['role'] in [PostgresqlRole.PRIMARY, PostgresqlRole.REPLICA, PostgresqlRole.STANDBY_LEADER]:
555+
if role in ['primary', 'replica', 'standby-leader']:
556556
if state != PostgresqlState.RUNNING:
557557
return
558558
return self.register_service(service_name, **params)

patroni/dcs/kubernetes.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
from ..collections import EMPTY_DICT
2525
from ..exceptions import DCSError
26-
from ..postgresql.misc import PostgresqlRole, PostgresqlState
26+
from ..postgresql.misc import PostgresqlState
2727
from ..postgresql.mpp import AbstractMPP
2828
from ..utils import deep_compare, iter_response_objects, \
2929
keepalive_socket_options, Retry, RetryFailedError, tzutc, uri, USER_AGENT
@@ -1324,7 +1324,7 @@ def touch_member(self, data: Dict[str, Any]) -> bool:
13241324
role = self._standby_leader_label_value \
13251325
if data['role'] == PostgresqlRole.STANDBY_LEADER else self._leader_label_value
13261326
tmp_role = 'primary'
1327-
elif data['state'] == PostgresqlState.RUNNING and data['role'] != PostgresqlRole.PRIMARY:
1327+
elif data['state'] == PostgresqlState.RUNNING and data['role'] != 'primary':
13281328
role = {'replica': self._follower_label_value}.get(data['role'], data['role'])
13291329
tmp_role = data['role']
13301330
else:
@@ -1333,7 +1333,14 @@ def touch_member(self, data: Dict[str, Any]) -> bool:
13331333

13341334
role_labels = {self._role_label: role}
13351335
if self._tmp_role_label:
1336-
role_labels[self._tmp_role_label] = tmp_role
1336+
updated_labels[self._tmp_role_label] = tmp_role
1337+
1338+
if self._bootstrap_labels:
1339+
if data['state'] in (PostgresqlState.INITDB, PostgresqlState.CUSTOM_BOOTSTRAP,
1340+
PostgresqlState.BOOTSTRAP_STARTING, PostgresqlState.CREATING_REPLICA):
1341+
updated_labels.update(self._bootstrap_labels)
1342+
else:
1343+
updated_labels.update({k: None for k, _ in self._bootstrap_labels.items()})
13371344

13381345
member = cluster and cluster.get_member(self._name, fallback_to_leader=False)
13391346
pod_labels = member and member.data.pop('pod_labels', None)

patroni/ha.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from .dcs import AbstractDCS, Cluster, Leader, Member, RemoteMember, Status, SyncState
1818
from .exceptions import DCSError, PatroniFatalException, PostgresConnectionException
1919
from .postgresql.callback_executor import CallbackAction
20-
from .postgresql.misc import postgres_version_to_int, PostgresqlRole, PostgresqlState
20+
from .postgresql.misc import postgres_version_to_int, PostgresqlState
2121
from .postgresql.postmaster import PostmasterProcess
2222
from .postgresql.rewind import Rewind
2323
from .quorum import QuorumStateResolver
@@ -474,7 +474,8 @@ def touch_member(self) -> bool:
474474
data['pending_restart'] = True
475475
data['pending_restart_reason'] = dict(self.state_handler.pending_restart_reason)
476476
if self._async_executor.scheduled_action in (None, 'promote') \
477-
and data['state'] in ['running', 'restarting', 'starting']:
477+
and data['state'] in [PostgresqlState.RUNNING, PostgresqlState.RESTARTING,
478+
PostgresqlState.STARTING]:
478479
try:
479480
timeline, wal_position, pg_control_timeline = self.state_handler.timeline_wal_position()
480481
data['xlog_location'] = self._last_wal_lsn = wal_position
@@ -514,7 +515,7 @@ def touch_member(self) -> bool:
514515
ret = self.dcs.touch_member(data)
515516
if ret:
516517
new_state = (data['state'], data['role'])
517-
if self._last_state != new_state and new_state == (PostgresqlState.RUNNING, PostgresqlRole.PRIMARY):
518+
if self._last_state != new_state and new_state == (PostgresqlState.RUNNING, 'primary'):
518519
self.notify_mpp_coordinator('after_promote')
519520
self._last_state = new_state
520521
return ret
@@ -660,7 +661,7 @@ def recover(self) -> str:
660661
and data.get('Database cluster state') in ('in production', 'in crash recovery',
661662
'shutting down', 'shut down')\
662663
and self.state_handler.state == PostgresqlState.CRASHED\
663-
and self.state_handler.role == PostgresqlRole.PRIMARY\
664+
and self.state_handler.role == 'primary'\
664665
and not self.state_handler.config.recovery_conf_exists():
665666
# We know 100% that we were running as a primary a few moments ago, therefore could just start postgres
666667
msg = 'starting primary after failure'
@@ -1183,7 +1184,7 @@ def update_failsafe(self, data: Dict[str, Any]) -> Union[int, str, None]:
11831184
11841185
:returns: the reason why caller shouldn't continue as a primary or the current value of received/replayed LSN.
11851186
"""
1186-
if self.state_handler.state == PostgresqlState.RUNNING and self.state_handler.role == PostgresqlRole.PRIMARY:
1187+
if self.state_handler.state == PostgresqlState.RUNNING and self.state_handler.role == 'primary':
11871188
return 'Running as a leader'
11881189
self._failsafe.update(data)
11891190
return self._last_wal_lsn
@@ -1919,7 +1920,7 @@ def after_start() -> None:
19191920
elif res is None:
19201921
return (False, 'postgres is still starting')
19211922
else:
1922-
return (False, 'restart failed')
1923+
return (False, PostgresqlState.RESTART_FAILED)
19231924

19241925
def _do_reinitialize(self, cluster: Cluster) -> Optional[bool]:
19251926
self.state_handler.stop('immediate', stop_timeout=self.patroni.config['retry_timeout'])
@@ -2059,7 +2060,8 @@ def handle_starting_instance(self) -> Optional[str]:
20592060
if not self.state_handler.check_for_startup() or self.is_paused():
20602061
self.set_start_timeout(None)
20612062
if self.is_paused():
2062-
self.state_handler.set_state(self.state_handler.is_running() and 'running' or 'stopped')
2063+
self.state_handler.set_state(PostgresqlState.RUNNING if self.state_handler.is_running()
2064+
else PostgresqlState.STOPPED)
20632065
return None
20642066

20652067
# state_handler.state == 'starting' here
@@ -2225,7 +2227,7 @@ def _run_cycle(self) -> str:
22252227

22262228
if not self.state_handler.is_healthy():
22272229
if self.is_paused():
2228-
self.state_handler.set_state('stopped')
2230+
self.state_handler.set_state(PostgresqlState.STOPPED)
22292231
if self.has_lock():
22302232
self._delete_leader()
22312233
return 'removed leader lock because postgres is not running'
@@ -2238,8 +2240,8 @@ def _run_cycle(self) -> str:
22382240
(self._rewind.is_needed and self._rewind.can_rewind_or_reinitialize_allowed):
22392241
return 'postgres is not running'
22402242

2241-
if self.state_handler.state in ('running', 'starting'):
2242-
self.state_handler.set_state('crashed')
2243+
if self.state_handler.state in (PostgresqlState.RUNNING, PostgresqlState.STARTING):
2244+
self.state_handler.set_state(PostgresqlState.CRASHED)
22432245
# try to start dead postgres
22442246
return self.recover()
22452247

0 commit comments

Comments
 (0)