def quorum_update(self, quorum: int, voters: CaseInsensitiveSet, leader: Optional[str] = None,
                      adjust_quorum: Optional[bool] = True) -> Iterator[Transition]:
        """Updates :attr:`quorum`, :attr:`voters` and optionally :attr:`leader` fields.

        :param quorum: the new value for :attr:`quorum`, could be adjusted depending
                       on values of :attr:`numsync_confirmed` and *adjust_quorum*.
        :param voters: the new value for :attr:`voters`, could be adjusted if :attr:`numsync_confirmed` == ``0``.
        :param leader: the new value for :attr:`leader`, optional.
        :param adjust_quorum: if set to ``True`` the quorum requirement will be increased by the
                              difference between :attr:`numsync` and :attr:`numsync_confirmed`.

        :yields: the new state of the ``/sync`` key as a :class:`Transition` object.

        :raises:
            :exc:`QuorumError` in case of invalid data or if the invariant after transition could not be satisfied.
        """
        if quorum < 0:
            raise QuorumError(f'Quorum {quorum} < 0 of ({voters})')
        if quorum > 0 and quorum >= len(voters):
            raise QuorumError(f'Quorum {quorum} >= N of ({voters})')

        old_leader = self.leader
        if leader is not None:  # Change of leader was requested
            self.leader = leader
        elif self.numsync_confirmed == 0 and not self.voters:
            # If there are no nodes that known to caught up with the primary we want to reset quorum/voters in /sync key
            quorum = 0
            voters = CaseInsensitiveSet()
        elif adjust_quorum:
            # It could be that the number of nodes that are known to catch up with the primary is below desired numsync.
            # We want to increase quorum to guarantee that the sync node will be found during the leader race.
            quorum += max(self.numsync - self.numsync_confirmed, 0)

        if (self.leader, quorum, voters) == (old_leader, self.quorum, self.voters):
            if self.voters:
                return
            # If transition produces no change of leader/quorum/voters we want to give a hint to
            # the caller to fetch the new state from the database and restart QuorumStateResolver.
            yield Transition('restart', self.leader, self.quorum, self.voters)

        self.quorum = quorum
        self.voters = voters
        self.check_invariants()
        logger.debug('quorum %s %s %s', self.leader, self.quorum, self.voters)
        yield Transition('quorum', self.leader, self.quorum, self.voters)
Updates :attr:`quorum`, :attr:`voters` and optionally :attr:`leader` fields.

        :param quorum: the new value for :attr:`quorum`, could be adjusted depending
                       on values of :attr:`numsync_confirmed` and *adjust_quorum*.
        :param voters: the new value for :attr:`voters`, could be adjusted if :attr:`numsync_confirmed` == ``0``.
        :param leader: the new value for :attr:`leader`, optional.
        :param adjust_quorum: if set to ``True`` the quorum requirement will be increased by the
                              difference between :attr:`numsync` and :attr:`numsync_confirmed`.

        :yields: the new state of the ``/sync`` key as a :class:`Transition` object.

        :raises:
            :exc:`QuorumError` in case of invalid data or if the invariant after transition could not be satisfied.
        
patroni/quorum.py