void ASIOConnection::refresh(Milliseconds timeout, RefreshCallback cb) {
    auto op = _impl.get();

    _refreshCallback = std::move(cb);

    // Actually timeout refreshes
    setTimeout(timeout,
               [this]() {
                   asio::post(_global->_impl->_io_service,
                              [this] { _impl->connection().stream().cancel(); });
               });

    // Our pings are isMaster's
    auto beginStatus = op->beginCommand(makeIsMasterRequest(this),
                                        NetworkInterfaceASIO::AsyncCommand::CommandType::kRPC,
                                        _hostAndPort);
    if (!beginStatus.isOK()) {
        auto cb = std::move(_refreshCallback);
        cb(this, beginStatus);
        return;
    }

    _global->_impl->_asyncRunCommand(
        op,
        [this, op](std::error_code ec, size_t bytes) {
            cancelTimeout();

            auto cb = std::move(_refreshCallback);

            if (ec)
                return cb(this, Status(ErrorCodes::HostUnreachable, ec.message()));

            cb(this, Status::OK());
        });
}
void ASIOConnection::refresh(Milliseconds timeout, RefreshCallback cb) {
    _impl->strand().dispatch([this, timeout, cb] {
        auto op = _impl.get();

        // We clear state transitions because we're re-running a portion of the asio state machine
        // without entering in startCommand (which would call this for us).
        op->clearStateTransitions();

        _refreshCallback = std::move(cb);

        // Actually timeout refreshes
        setTimeout(timeout, [this] { _impl->connection().stream().cancel(); });

        // Our pings are isMaster's
        auto beginStatus = op->beginCommand(makeIsMasterRequest(this),
                                            NetworkInterfaceASIO::AsyncCommand::CommandType::kRPC,
                                            _hostAndPort);
        if (!beginStatus.isOK()) {
            auto cb = std::move(_refreshCallback);
            cb(this, beginStatus);
            return;
        }

        // If we fail during refresh, the _onFinish function of the AsyncOp will get called. As such
        // we
        // need to intercept those calls so we can capture them. This will get cleared out when we
        // fill
        // in the real onFinish in startCommand.
        op->setOnFinish([this](StatusWith<RemoteCommandResponse> failedResponse) {
            invariant(!failedResponse.isOK());
            auto cb = std::move(_refreshCallback);
            cb(this, failedResponse.getStatus());
        });

        op->_inRefresh = true;

        _global->_impl->_asyncRunCommand(op, [this, op](std::error_code ec, size_t bytes) {
            cancelTimeout();

            auto cb = std::move(_refreshCallback);

            if (ec)
                return cb(this, Status(ErrorCodes::HostUnreachable, ec.message()));

            op->_inRefresh = false;
            cb(this, Status::OK());
        });
    });
}