Uploaded image for project: 'Solr'
  1. Solr
  2. SOLR-13605

HttpSolrClient.Builder.withHttpClient() is useless for the purpose of setting client scoped so/connect timeouts

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • None
    • main (10.0), 9.3
    • None
    • None

    Description

      TL;DR: trying to use HttpSolrClient.Builder.withHttpClient is useless for the the purpose of specifying an HttpClient with the default "timeouts" you want to use on all requests, because of how HttpSolrClient.Builder and HttpClientUtil.createDefaultRequestConfigBuilder() hardcode values thta get set on every HttpRequest.

      This internally affects code that uses things like UpdateShardHandler.getDefaultHttpClient(), UpdateShardHandler.getUpdateOnlyHttpClient() UpdateShardHandler.getRecoveryOnlyHttpClient(), etc...


      While looking into the patch in SOLR-13532, I realized that the way HttpSolrClient.Builder and it's super class SolrClientBuilder work, the following code doesn't do what a reasonable person would expect...

      SolrParams clientParams = params(HttpClientUtil.PROP_SO_TIMEOUT, 12345,
                                       HttpClientUtil.PROP_CONNECTION_TIMEOUT, 67890);
      HttpClient httpClient = HttpClientUtil.createClient(clientParams);
      HttpSolrClient solrClient = new HttpSolrClient.Builder(ANY_BASE_SOLR_URL)
              .withHttpClient(httpClient)
              .build();
      

      When solrClient is used to execute a request, neither of the properties passed to HttpClientUtil.createClient(...) will matter - the HttpSolrClient.Builder (via inheritence from SolrClientBuilder has the following hardcoded values...

        // SolrClientBuilder
        protected Integer connectionTimeoutMillis = 15000;
        protected Integer socketTimeoutMillis = 120000;
      

      ...which unless overridden by calls to withConnectionTimeout() and withSocketTimeout() will get set on the HttpSolrClient object, and used on every request...

          // protected HttpSolrClient constructor
          this.connectionTimeout = builder.connectionTimeoutMillis;
          this.soTimeout = builder.socketTimeoutMillis;
      
      

      It would be tempting to try and do something like this to work around the problem...

      SolrParams clientParams = params(HttpClientUtil.PROP_SO_TIMEOUT, 12345,
                                       HttpClientUtil.PROP_CONNECTION_TIMEOUT, 67890);
      HttpClient httpClient = HttpClientUtil.createClient(clientParams);
      HttpSolrClient solrClient = new HttpSolrClient.Builder(ANY_BASE_SOLR_URL)
              .withHttpClient(httpClient)
              .withSocketTimeout(null)
              .withConnectionTimeout(null)
              .build();
      

      ...except for 2 problems:

      1. In HttpSolrClient.executeMethod, if the values of this.connectionTimeout or this.soTimeout are null, then the values from HttpClientUtil.createDefaultRequestConfigBuilder(); get used, which has it's own hardcoded defaults.
      2. withSocketTimeout and withConnectionTimeout take an int, not a (nullable) Integer.

      So then maybe something like this would work? - particularly since at the HttpClient / HttpRequest / RequestConfig level, a "-1" set on the HttpRequest's RequestConfig is suppose to mean "use the (client) default" ...

      SolrParams clientParams = params(HttpClientUtil.PROP_SO_TIMEOUT, 12345,
                                       HttpClientUtil.PROP_CONNECTION_TIMEOUT, 67890);
      HttpClient httpClient = HttpClientUtil.createClient(clientParams);
      HttpSolrClient client = new HttpSolrClient.Builder(ANY_BASE_SOLR_URL)
              .withHttpClient(httpClient)
              .withSocketTimeout(-1)
              .withConnectionTimeout(-1)
              .build();
      

      ...except that if we do that we get an IllegalArgumentException...

        // SolrClientBuilder
        public B withConnectionTimeout(int connectionTimeoutMillis) {
          if (connectionTimeoutMillis < 0) {
            throw new IllegalArgumentException("connectionTimeoutMillis must be a non-negative integer.");
          }
      

      This is madness, and eliminates most/all of the known value of using .withHttpClient

      Attachments

        Issue Links

          Activity

            People

              epugh Eric Pugh
              hossman Chris M. Hostetter
              Votes:
              1 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 3h 10m
                  3h 10m