microsoft / cpprestsdk

The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
Other
8.01k stars 1.66k forks source link

Parallel http_request requests block _before_ being placed sometimes #1610

Open vkapartzianis opened 3 years ago

vkapartzianis commented 3 years ago

I use the function below to send requests in parallel, 2-16 at a time, to an internal service. Sometimes, one of the requests just blocks. The client logs the request (as below) but the service never receives it.

In other words, the client logs let's say 6 requests, 5 replies, and just heartbeats afterwards, while the service logs 5 requests and 5 replies. So I can only assume that client.request(request) blocks for some reason. That's on Windows Server 2019, so I don't think the thread pool is an issue.

pplx::task<json::value> RequestJSONAsync(http_client& client, string_t& request_uri)
{
    // Log the request uri for debugging purposes
    CFileLog::WriteLine(LOG_DEBUG, utility::conversions::to_utf8string(request_uri));

    // Manually build up an HTTP request with a header that specifies the content type and the request URI
    http_request request(methods::GET);
    request.headers().set_content_type(L"application/json");
    request.set_request_uri(request_uri);

    // Make an HTTP GET request and asynchronously process the response
    return client.request(request)
        // Continue when the response is available
        .then([](pplx::task<http_response> response)
        {
            const http_response& r = response.get();

            // Log non-OK status code as error
            if (r.status_code() != status_codes::OK)
            {
                CFileLog::Log(LOG_WARN, "HTTP status: " + std::to_string(r.status_code()));
            }

            // Response may still be valid JSON
            return r.extract_json();
        })
        // Continue when the JSON value is available
        .then([](pplx::task<json::value> value)
        {
            try
            {
                const json::value& v = value.get();

                // Log the value we received
                CFileLog::Log(LOG_DEBUG, utility::conversions::to_utf8string(v.serialize()));

                return v;
            }
            catch (const http_exception& e)
            {
                // Log error
                CFileLog::Log(LOG_ERROR, boost::replace_all_copy(std::string(e.what()), "\r\n", "\\r\\n"));

                return json::value();
            }
        });
}