def follow(self, member: Union[Leader, Member, None], role: PostgresqlRole = PostgresqlRole.REPLICA,
               timeout: Optional[float] = None, do_reload: bool = False) -> Optional[bool]:
        """Reconfigure postgres to follow a new member or use different recovery parameters.

        Method may call `on_role_change` callback if role is changing.

        :param member: The member to follow
        :param role: The desired role, one of :class:`~misc.PostgresqlRole` values, normally
            :class:`~misc.PostgresqlRole.REPLICA`, but could also be a :class:`~misc.PostgresqlRole.STANDBY_LEADER`
        :param timeout: start timeout, how long should the `start()` method wait for postgres accepting connections
        :param do_reload: indicates that after updating postgresql.conf we just need to do a reload instead of restart

        :returns: True - if restart/reload were successfully performed,
                  False - if restart/reload failed
                  None - if nothing was done or if Postgres is still in starting state after `timeout` seconds."""

        if not self.ensure_major_version_is_known():
            return None

        recovery_params = self.config.build_recovery_params(member)
        self.config.write_recovery_conf(recovery_params)

        # When we demoting the primary or standby_leader to replica or promoting replica to a standby_leader
        # and we know for sure that postgres was already running before, we will only execute on_role_change
        # callback and prevent execution of on_restart/on_start callback.
        # If the role remains the same (replica or standby_leader), we will execute on_start or on_restart
        change_role = self.cb_called and \
            (self.role in (PostgresqlRole.PRIMARY, PostgresqlRole.DEMOTED)
             or not {PostgresqlRole.STANDBY_LEADER, PostgresqlRole.REPLICA} - {self.role, role})
        if change_role:
            self.__cb_pending = CallbackAction.NOOP

        ret = True
        if self.is_running():
            if do_reload:
                self.config.write_postgresql_conf()
                ret = self.reload(block_callbacks=change_role)
                if ret and change_role:
                    self.set_role(role)
            else:
                ret = self.restart(block_callbacks=change_role, role=role)
        else:
            ret = self.start(timeout=timeout, block_callbacks=change_role, role=role) or None

        if change_role:
            # TODO: postpone this until start completes, or maybe do even earlier
            self.call_nowait(CallbackAction.ON_ROLE_CHANGE)
        return ret
Reconfigure postgres to follow a new member or use different recovery parameters.

        Method may call `on_role_change` callback if role is changing.

        :param member: The member to follow
        :param role: The desired role, one of :class:`~misc.PostgresqlRole` values, normally
            :class:`~misc.PostgresqlRole.REPLICA`, but could also be a :class:`~misc.PostgresqlRole.STANDBY_LEADER`
        :param timeout: start timeout, how long should the `start()` method wait for postgres accepting connections
        :param do_reload: indicates that after updating postgresql.conf we just need to do a reload instead of restart

        :returns: True - if restart/reload were successfully performed,
                  False - if restart/reload failed
                  None - if nothing was done or if Postgres is still in starting state after `timeout` seconds.
patroni/postgresql/__init__.py