patroni.postgresql.sync module¶
-
class
patroni.postgresql.sync.
SyncHandler
(postgresql: Postgresql)¶ Bases:
object
Class responsible for working with the synchronous_standby_names.
Sync standbys are chosen based on their state in pg_stat_replication. When synchronous_standby_names is changed we memorize the _primary_flush_lsn and the current_state() method will count newly added names as “sync” only when they reached memorized LSN and also reported as “sync” by pg_stat_replication
-
__init__
(postgresql: Postgresql) → None¶ Initialize self. See help(type(self)) for accurate signature.
-
_handle_synchronous_standby_names_change
() → None¶ Handles changes of “synchronous_standby_names” GUC.
If “synchronous_standby_names” was changed, we need to check that newly added replicas have reached self._primary_flush_lsn. Only after that they could be counted as synchronous.
-
_process_replica_readiness
(cluster: patroni.dcs.Cluster, replica_list: patroni.postgresql.sync._ReplicaList) → None¶ Flags replicas as truly “synchronous” when they have caught up with
_primary_flush_lsn
.Parameters: - cluster – current cluster topology from DCS
- replica_list – collection of replicas that we want to evaluate.
-
current_state
(cluster: patroni.dcs.Cluster) → patroni.postgresql.sync._SyncState¶ Find the best candidates to be the synchronous standbys.
Current synchronous standby is always preferred, unless it has disconnected or does not want to be a synchronous standby any longer.
Standbys are selected based on values from the global configuration:
maximum_lag_on_syncnode
: would help swapping unhealthy sync replica in case it stops responding (or hung). Please set the value high enough, so it won’t unnecessarily swap sync standbys during high loads. Any value less or equal to0
keeps the behavior backwards compatible. Please note that it will also not swap sync standbys when all replicas are hung.synchronous_node_count
: controls how many nodes should be set as synchronous.
Parameters: cluster – current cluster topology from DCS Returns: current synchronous replication state as a _SyncState
object
-
set_synchronous_standby_names
(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.Parameters: - sync – set of nodes to sync to
- num – specifies number of nodes to sync to. The num is set only in case if quorum commit is enabled
-
-
class
patroni.postgresql.sync.
_Replica
¶ Bases:
tuple
Class representing a single replica that is eligible to be synchronous.
Attributes are taken from
pg_stat_replication
view and respectiveCluster.members
.Variables: - pid – PID of walsender process.
- application_name – matches with the
Member.name
. - sync_state – possible values are:
async
,potential
,quorum
, andsync
. - lsn –
write_lsn
,flush_lsn
, orreplay_lsn
, depending on the value ofsynchronous_commit
GUC. - nofailover – whether the corresponding member has
nofailover
tag set toTrue
.
-
_asdict
()¶ Return a new dict which maps field names to their values.
-
_field_defaults
= {}¶
-
_field_types
= {'application_name': <class 'str'>, 'lsn': <class 'int'>, 'nofailover': <class 'bool'>, 'pid': <class 'int'>, 'sync_state': <class 'str'>}¶
-
_fields
= ('pid', 'application_name', 'sync_state', 'lsn', 'nofailover')¶
-
_fields_defaults
= {}¶
-
classmethod
_make
(iterable)¶ Make a new _Replica object from a sequence or iterable
-
_replace
(**kwds)¶ Return a new _Replica object replacing specified fields with new values
-
application_name
¶ Alias for field number 1
-
lsn
¶ Alias for field number 3
-
nofailover
¶ Alias for field number 4
-
pid
¶ Alias for field number 0
-
sync_state
¶ Alias for field number 2
-
class
patroni.postgresql.sync.
_ReplicaList
(postgresql: Postgresql, cluster: patroni.dcs.Cluster)¶ Bases:
list
,typing.Generic
A collection of :class:
_Replica
objects.Values are reverse ordered by
_Replica.sync_state
and_Replica.lsn
. That is, first there will be replicas that havesync_state
==sync
, even if they are not the most up-to-date in term of write/flush/replay LSN. It helps to keep the result of chosing new synchronous nodes consistent in case if a synchronous standby member is slowed down OR async node is receiving changes faster than the sync member. Such cases would trigger sync standby member swapping, but only if lag on this member is exceeding a threshold (maximum_lag_on_syncnode
).Variables: max_lsn – maximum value of _Replica.lsn
among all values. In case if there is just one element in the list we take value ofpg_current_wal_flush_lsn()
.-
__init__
(postgresql: Postgresql, cluster: patroni.dcs.Cluster) → None¶ Create :class:
_ReplicaList
object.Parameters: - postgresql – reference to :class:
Postgresql
object. - cluster – currently known cluster state from DCS.
- postgresql – reference to :class:
-
-
class
patroni.postgresql.sync.
_SSN
¶ Bases:
tuple
class representing “synchronous_standby_names” value after parsing.
Variables: -
_asdict
()¶ Return a new dict which maps field names to their values.
-
_field_defaults
= {}¶
-
_field_types
= {'has_star': <class 'bool'>, 'members': <class 'patroni.collections.CaseInsensitiveSet'>, 'num': <class 'int'>, 'sync_type': <class 'str'>}¶
-
_fields
= ('sync_type', 'has_star', 'num', 'members')¶
-
_fields_defaults
= {}¶
-
classmethod
_make
(iterable)¶ Make a new _SSN object from a sequence or iterable
-
_replace
(**kwds)¶ Return a new _SSN object replacing specified fields with new values
-
has_star
¶ Alias for field number 1
-
members
¶ Alias for field number 3
-
num
¶ Alias for field number 2
-
sync_type
¶ Alias for field number 0
-
-
class
patroni.postgresql.sync.
_SyncState
¶ Bases:
tuple
Class representing the current synchronous state.
Variables: - sync_type – possible values:
off
,priority
,quorum
- numsync – how many nodes are required to be synchronous (according to
synchronous_standby_names
). Is0
ifsynchronous_standby_names
value is invalid or contains*
. - numsync_confirmed – how many nodes are known to be synchronous according to the
pg_stat_replication
view. Only nodes that caught up with theSyncHandler._primary_flush_lsn
are counted. - sync – collection of synchronous node names. In case of quorum commit all nodes listed
in
synchronous_standby_names
, otherwise nodes that are confirmed to be synchronous according to thepg_stat_replication
view. - active – collection of node names that are streaming and have no restrictions to become synchronous.
-
_asdict
()¶ Return a new dict which maps field names to their values.
-
_field_defaults
= {}¶
-
_field_types
= {'active': <class 'patroni.collections.CaseInsensitiveSet'>, 'numsync': <class 'int'>, 'numsync_confirmed': <class 'int'>, 'sync': <class 'patroni.collections.CaseInsensitiveSet'>, 'sync_type': <class 'str'>}¶
-
_fields
= ('sync_type', 'numsync', 'numsync_confirmed', 'sync', 'active')¶
-
_fields_defaults
= {}¶
-
classmethod
_make
(iterable)¶ Make a new _SyncState object from a sequence or iterable
-
_replace
(**kwds)¶ Return a new _SyncState object replacing specified fields with new values
-
active
¶ Alias for field number 4
-
numsync
¶ Alias for field number 1
-
numsync_confirmed
¶ Alias for field number 2
-
sync
¶ Alias for field number 3
-
sync_type
¶ Alias for field number 0
- sync_type – possible values:
-
patroni.postgresql.sync.
parse_sync_standby_names
(value: str) → patroni.postgresql.sync._SSN¶ Parse postgresql synchronous_standby_names to constituent parts.
Parameters: value – the value of synchronous_standby_names Returns: _SSN
objectRaises: ValueError – if the configuration value can not be parsed >>> parse_sync_standby_names('').sync_type 'off'
>>> parse_sync_standby_names('FiRsT').sync_type 'priority'
>>> 'first' in parse_sync_standby_names('FiRsT').members True
>>> set(parse_sync_standby_names('"1"').members) {'1'}
>>> parse_sync_standby_names(' a , b ').members == {'a', 'b'} True
>>> parse_sync_standby_names(' a , b ').num 1
>>> parse_sync_standby_names('ANY 4("a",*,b)').has_star True
>>> parse_sync_standby_names('ANY 4("a",*,b)').num 4
>>> parse_sync_standby_names('1') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValueError: Unparseable synchronous_standby_names value
>>> parse_sync_standby_names('a,') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValueError: Unparseable synchronous_standby_names value
>>> parse_sync_standby_names('ANY 4("a" b,"c c")') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValueError: Unparseable synchronous_standby_names value
>>> parse_sync_standby_names('FIRST 4("a",)') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValueError: Unparseable synchronous_standby_names value
>>> parse_sync_standby_names('2 (,)') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValueError: Unparseable synchronous_standby_names value
-
patroni.postgresql.sync.
quote_standby_name
(value: str) → str¶ Quote provided value if it is nenecessary.
Parameters: value – name of a synchronous standby. Returns: a quoted value if it is required or the original one.