diff --git a/patroni/config.py b/patroni/config.py index 88efa057..99ce58f1 100644 --- a/patroni/config.py +++ b/patroni/config.py @@ -96,7 +96,7 @@ class GlobalConfig(object): @property def is_quorum_commit_mode(self) -> bool: - """:returns: `True` if quorum commit replication is requested""" + """:returns: ``True`` if quorum commit replication is requested""" return str(self.get('synchronous_mode')).lower() == 'quorum' @property diff --git a/patroni/dcs/__init__.py b/patroni/dcs/__init__.py index a50f3dce..36e91121 100644 --- a/patroni/dcs/__init__.py +++ b/patroni/dcs/__init__.py @@ -615,8 +615,9 @@ class SyncState(NamedTuple): :ivar version: modification version of a synchronization key in a Configuration Store. :ivar leader: reference to member that was leader. :ivar sync_standby: synchronous standby list (comma delimited) which are last synchronized to leader. - :ivar quorum: if the node from sync_standby list is doing a leader race it should - see at least quorum other nodes from the sync_standby + leader list. + :ivar quorum: if the node from :attr:`~SyncState.sync_standby` list is doing a leader race it should + see at least :attr:`~SyncState.quorum` other nodes from the + :attr:`~SyncState.sync_standby` + :attr:`~SyncState.leader` list. """ version: Optional[_Version] @@ -1949,8 +1950,9 @@ class AbstractDCS(abc.ABC): :param leader: name of the leader node that manages ``/sync`` key. :param sync_standby: collection of currently known synchronous standby node names. - :param quorum: if the node from sync_standby list is doing a leader race it should - see at least quorum other nodes from the sync_standby + leader list + :param quorum: if the node from :attr:`~SyncState.sync_standby` list is doing a leader race it should + see at least :attr:`~SyncState.quorum` other nodes from the + :attr:`~SyncState.sync_standby` + :attr:`~SyncState.leader` list :returns: dictionary that later could be serialized to JSON or saved directly to DCS. """ @@ -1967,8 +1969,9 @@ class AbstractDCS(abc.ABC): :param leader: name of the leader node that manages ``/sync`` key. :param sync_standby: collection of currently known synchronous standby node names. :param version: for conditional update of the key/object. - :param quorum: if the node from sync_standby list is doing a leader race it should - see at least quorum other nodes from the sync_standby + leader list + :param quorum: if the node from :attr:`~SyncState.sync_standby` list is doing a leader race it should + see at least :attr:`~SyncState.quorum` other nodes from the + :attr:`~SyncState.sync_standby` + :attr:`~SyncState.leader` list :returns: the new :class:`SyncState` object or ``None``. """ diff --git a/patroni/postgresql/sync.py b/patroni/postgresql/sync.py index 067583d7..169f5f00 100644 --- a/patroni/postgresql/sync.py +++ b/patroni/postgresql/sync.py @@ -354,7 +354,9 @@ END;$$""") for replica in sorted(replica_list, key=lambda x: x.nofailover): if sync_node_maxlag <= 0 or replica_list.max_lsn - replica.lsn <= sync_node_maxlag: if self._postgresql.global_config.is_quorum_commit_mode: - # add nodes with nofailover tag only to get enough "active" nodes + # We do not add nodes with `nofailover` enabled because that reduces availability. + # We need to check LSN quorum only among nodes that are promotable because + # there is a chance that a non-promotable node is ahead of a promotable one. if not replica.nofailover or len(active) < sync_node_count: if replica.application_name in self._ready_replicas: numsync_confirmed += 1 @@ -379,6 +381,9 @@ END;$$""") def set_synchronous_standby_names(self, sync: Collection[str], num: Optional[int] = None) -> None: """Constructs and sets ``synchronous_standby_names`` GUC value. + + .. note:: + standbys in ``synchronous_standby_names`` will be sorted by name. :param sync: set of nodes to sync to :param num: specifies number of nodes to sync to. The *num* is set only in case if quorum commit is enabled