def _generate_transitions(self) -> Iterator[Transition]:
        """Produce a set of changes to safely transition from the current state to the desired.

        :yields: transitions as :class:`Transition` objects.
        """
        logger.debug("Quorum state: leader %s quorum %s, voters %s, numsync %s, sync %s, "
                     "numsync_confirmed %s, active %s, sync_wanted %s leader_wanted %s",
                     self.leader, self.quorum, self.voters, self.numsync, self.sync,
                     self.numsync_confirmed, self.active, self.sync_wanted, self.leader_wanted)
        try:
            if self.leader_wanted != self.leader:  # failover
                voters = (self.voters - CaseInsensitiveSet([self.leader_wanted])) | CaseInsensitiveSet([self.leader])
                if not self.sync:
                    # If sync is empty we need to update synchronous_standby_names first
                    numsync = len(voters) - self.quorum
                    yield from self.sync_update(numsync, CaseInsensitiveSet(voters))
                # If leader changed we need to add the old leader to quorum (voters)
                yield from self.quorum_update(self.quorum, CaseInsensitiveSet(voters), self.leader_wanted)
                # right after promote there could be no replication connections yet
                if not self.sync & self.active:
                    return  # give another loop_wait seconds for replicas to reconnect before removing them from quorum
            else:
                self.check_invariants()
        except QuorumError as e:
            logger.warning('%s', e)
            yield from self.quorum_update(len(self.sync) - self.numsync, self.sync)

        assert self.leader == self.leader_wanted

        # numsync_confirmed could be 0 after restart/failover, we will calculate it from quorum
        if self.numsync_confirmed == 0 and self.sync & self.active:
            self.numsync_confirmed = min(len(self.sync & self.active), len(self.voters) - self.quorum)
            logger.debug('numsync_confirmed=0, adjusting it to %d', self.numsync_confirmed)

        yield from self.__handle_non_steady_cases()

        # We are in a steady state point. Find if desired state is different and act accordingly.

        yield from self.__remove_gone_nodes()

        yield from self.__add_new_nodes()

        yield from self.__handle_replication_factor_change()
Produce a set of changes to safely transition from the current state to the desired.

        :yields: transitions as :class:`Transition` objects.
        
patroni/quorum.py