def is_failover_possible(self, *, cluster_lsn: int = 0, exclude_failover_candidate: bool = False) -> bool:
        """Checks whether any of the cluster members is allowed to promote and is healthy enough for that.

        :param cluster_lsn: to calculate replication lag and exclude member if it is lagging.
        :param exclude_failover_candidate: if ``True``, exclude :attr:`failover.candidate` from the members
                                           list against which the failover possibility checks are run.
        :returns: `True` if there are members eligible to become the new leader.
        """
        candidates = self.get_failover_candidates(exclude_failover_candidate)

        action = self._get_failover_action_name()
        if self.is_synchronous_mode() and self.cluster.failover and self.cluster.failover.candidate and not candidates:
            logger.warning('%s candidate=%s does not match with sync_standbys=%s',
                           action.title(), self.cluster.failover.candidate, self.cluster.sync.sync_standby)
        elif not candidates:
            logger.warning('%s: candidates list is empty', action)

        quorum_votes = -1
        cluster_timeline = self.cluster.timeline
        for st in self.fetch_nodes_statuses(candidates):
            not_allowed_reason = st.failover_limitation()
            if not_allowed_reason:
                logger.info('Member %s is %s', st.member.name, not_allowed_reason)
            elif cluster_lsn and st.wal_position < cluster_lsn or \
                    not cluster_lsn and self.is_lagging(st.wal_position):
                logger.info('Member %s exceeds maximum replication lag', st.member.name)
            elif self.check_timeline() and (not st.timeline or st.timeline < cluster_timeline):
                logger.info('Timeline %s of member %s is behind the cluster timeline %s',
                            st.timeline, st.member.name, cluster_timeline)
            else:
                quorum_votes += 1

        # In case of quorum replication we need to make sure that there is enough healthy synchronous replicas!
        # However, when failover candidate is set, we can ignore quorum requirements.
        check_quorum = self.quorum_commit_mode_is_active() and\
            not (self.cluster.failover and self.cluster.failover.candidate and not exclude_failover_candidate)
        if check_quorum and quorum_votes < self.cluster.sync.quorum:
            logger.info('Quorum requirement %d can not be reached', self.cluster.sync.quorum)
            return False

        return quorum_votes >= 0
Checks whether any of the cluster members is allowed to promote and is healthy enough for that.

        :param cluster_lsn: to calculate replication lag and exclude member if it is lagging.
        :param exclude_failover_candidate: if ``True``, exclude :attr:`failover.candidate` from the members
                                           list against which the failover possibility checks are run.
        :returns: `True` if there are members eligible to become the new leader.
        
patroni/ha.py