You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by tf...@apache.org on 2021/03/26 23:37:13 UTC

[lucene-solr] branch branch_8x updated: SOLR-15155: Let CloudHttp2SolrClient accept an external Http2SolrClient Builder (#15)

This is an automated email from the ASF dual-hosted git repository.

tflobbe pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/branch_8x by this push:
     new db44134  SOLR-15155: Let CloudHttp2SolrClient accept an external Http2SolrClient Builder (#15)
db44134 is described below

commit db44134e02662633c93f7789d802bfc1e499a4a4
Author: Tomas Fernandez Lobbe <tf...@apache.org>
AuthorDate: Fri Mar 26 16:17:23 2021 -0700

    SOLR-15155: Let CloudHttp2SolrClient accept an external Http2SolrClient Builder (#15)
    
    This allows configuring the internal client with things like timeouts, credentials, etc
---
 solr/CHANGES.txt                                   |  2 +
 .../client/solrj/impl/CloudHttp2SolrClient.java    | 34 ++++++++++++--
 .../impl/CloudHttp2SolrClientBuilderTest.java      | 54 +++++++++++++++++++++-
 3 files changed, 86 insertions(+), 4 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 6ab85e7..fcc26fa 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -46,6 +46,8 @@ Improvements
 
 * SOLR-11233: Add optional JAVA8_GC_LOG_FILE_OPTS for bin/solr. (Pranav Murugappan, Christine Poerschke)
 
+* SOLR-15155: Let CloudHttp2SolrClient accept an external Http2SolrClient Builder (Tomás Fernández Löbbe)
+
 Optimizations
 ---------------------
 * SOLR-15079: Block Collapse - Faster collapse code when groups are co-located via Block Join style nested doc indexing.
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudHttp2SolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudHttp2SolrClient.java
index 8e6ac82..3de79ca 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudHttp2SolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudHttp2SolrClient.java
@@ -44,7 +44,7 @@ public class CloudHttp2SolrClient  extends BaseCloudSolrClient {
 
   private final ClusterStateProvider stateProvider;
   private final LBHttp2SolrClient lbClient;
-  private Http2SolrClient myClient;
+  private final Http2SolrClient myClient;
   private final boolean clientIsInternal;
 
   /**
@@ -57,8 +57,17 @@ public class CloudHttp2SolrClient  extends BaseCloudSolrClient {
    */
   protected CloudHttp2SolrClient(Builder builder) {
     super(builder.shardLeadersOnly, builder.parallelUpdates, builder.directUpdatesToLeadersOnly);
-    this.clientIsInternal = builder.httpClient == null;
-    this.myClient = (builder.httpClient == null) ? new Http2SolrClient.Builder().build() : builder.httpClient;
+    if (builder.httpClient == null) {
+      this.clientIsInternal = true;
+      if (builder.internalClientBuilder == null) {
+        this.myClient = new Http2SolrClient.Builder().build();
+      } else {
+        this.myClient = builder.internalClientBuilder.build();
+      }
+    } else {
+      this.clientIsInternal = false;
+      this.myClient = builder.httpClient;
+    }
     if (builder.stateProvider == null) {
       if (builder.zkHosts != null && builder.solrUrls != null) {
         throw new IllegalArgumentException("Both zkHost(s) & solrUrl(s) have been specified. Only specify one.");
@@ -125,6 +134,7 @@ public class CloudHttp2SolrClient  extends BaseCloudSolrClient {
     protected boolean directUpdatesToLeadersOnly = false;
     protected boolean parallelUpdates = true;
     protected ClusterStateProvider stateProvider;
+    protected Http2SolrClient.Builder internalClientBuilder;
 
     /**
      * Provide a series of Solr URLs to be used when configuring {@link CloudHttp2SolrClient} instances.
@@ -207,11 +217,29 @@ public class CloudHttp2SolrClient  extends BaseCloudSolrClient {
     }
 
     public Builder withHttpClient(Http2SolrClient httpClient) {
+      if (this.internalClientBuilder != null) {
+        throw new IllegalStateException("The builder can't accept an httpClient AND an internalClientBuilder, only one of those can be provided");
+      }
       this.httpClient = httpClient;
       return this;
     }
 
     /**
+     * If provided, the CloudHttp2SolrClient will build it's internal Http2SolrClient using this builder
+     * (instead of the empty default one). Providing this builder allows users to configure the internal
+     * clients (authentication, timeouts, etc).
+     * @param internalClientBuilder the builder to use for creating the internal http client.
+     * @return this
+     */
+    public Builder withInternalClientBuilder(Http2SolrClient.Builder internalClientBuilder) {
+      if (this.httpClient != null) {
+        throw new IllegalStateException("The builder can't accept an httpClient AND an internalClientBuilder, only one of those can be provided");
+      }
+      this.internalClientBuilder = internalClientBuilder;
+      return this;
+    }
+
+    /**
      * Create a {@link CloudHttp2SolrClient} based on the provided configuration.
      */
     public CloudHttp2SolrClient build() {
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBuilderTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBuilderTest.java
index d841333..cb0a5df 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBuilderTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBuilderTest.java
@@ -25,6 +25,13 @@ import java.util.Optional;
 
 import org.apache.solr.SolrTestCase;
 import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 public class CloudHttp2SolrClientBuilderTest extends SolrTestCase {
   private static final String ANY_CHROOT = "/ANY_CHROOT";
@@ -70,7 +77,7 @@ public class CloudHttp2SolrClientBuilderTest extends SolrTestCase {
   @Test
   public void testByDefaultConfiguresClientToSendUpdatesOnlyToShardLeaders() throws IOException {
     try(CloudHttp2SolrClient createdClient = new CloudHttp2SolrClient.Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT)).build()) {
-      assertTrue(createdClient.isUpdatesToLeaders() == true);
+      assertTrue(createdClient.isUpdatesToLeaders());
     }
   }
 
@@ -81,4 +88,49 @@ public class CloudHttp2SolrClientBuilderTest extends SolrTestCase {
     }
   }
 
+  @Test
+  public void testExternalClientAndInternalBuilderTogether() {
+    assumeWorkingMockito();
+    expectThrows(IllegalStateException.class, () -> new CloudHttp2SolrClient.Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT))
+            .withHttpClient(Mockito.mock(Http2SolrClient.class))
+            .withInternalClientBuilder(Mockito.mock(Http2SolrClient.Builder.class))
+            .build());
+    expectThrows(IllegalStateException.class, () -> new CloudHttp2SolrClient.Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT))
+            .withInternalClientBuilder(Mockito.mock(Http2SolrClient.Builder.class))
+            .withHttpClient(Mockito.mock(Http2SolrClient.class))
+            .build());
+  }
+
+  @Test
+  public void testProvideInternalBuilder() throws IOException {
+    assumeWorkingMockito();
+    Http2SolrClient http2Client = Mockito.mock(Http2SolrClient.class);
+    Http2SolrClient.Builder http2ClientBuilder = Mockito.mock(Http2SolrClient.Builder.class);
+    when(http2ClientBuilder.build()).thenReturn(http2Client);
+    CloudHttp2SolrClient.Builder clientBuilder = new CloudHttp2SolrClient.Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT))
+            .withInternalClientBuilder(http2ClientBuilder);
+    verify(http2ClientBuilder, never()).build();
+    try (CloudHttp2SolrClient client = clientBuilder.build()) {
+      assertEquals(http2Client, client.getHttpClient());
+      verify(http2ClientBuilder, times(1)).build();
+      verify(http2Client, never()).close();
+    }
+    // it's internal, should be closed when closing CloudSolrClient
+    verify(http2Client, times(1)).close();
+  }
+
+  @Test
+  public void testProvideExternalClient() throws IOException {
+    assumeWorkingMockito();
+    Http2SolrClient http2Client = Mockito.mock(Http2SolrClient.class);
+    CloudHttp2SolrClient.Builder clientBuilder = new CloudHttp2SolrClient.Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT))
+            .withHttpClient(http2Client);
+    try (CloudHttp2SolrClient client = clientBuilder.build()) {
+      assertEquals(http2Client, client.getHttpClient());
+    }
+    // it's external, should be NOT closed when closing CloudSolrClient
+    verify(http2Client, never()).close();
+    http2Client.close();
+  }
+
 }