-
Notifications
You must be signed in to change notification settings - Fork 677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SOLR-17541: LBSolrClient implementations should agree on 'getClient()' semantics #2899
Changes from 24 commits
5261cd3
bc8c888
a249169
1f8a307
90bf9e2
51676f5
db76064
605bdc7
508af0d
39177b4
35651b8
19577dc
ca59536
67c8b8f
7b90862
1539d97
8f17279
effedb9
29a3445
50470cd
f423bd2
6176a99
783f815
e8c998d
e035a0c
99282aa
45b9e10
7df3c3b
90bd2ec
f984d12
28aec3b
30dcdb3
730aad0
071fb04
05eb1ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WDYT @iamsanjay ? |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,6 @@ | |
*/ | ||
package org.apache.solr.core; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.TimeUnit; | ||
import org.apache.solr.client.solrj.impl.Http2SolrClient; | ||
import org.apache.solr.common.util.IOUtils; | ||
|
@@ -37,14 +36,15 @@ final class HttpSolrClientProvider implements AutoCloseable { | |
|
||
private final Http2SolrClient httpSolrClient; | ||
|
||
private final Http2SolrClient.Builder httpClientBuilder; | ||
|
||
private final InstrumentedHttpListenerFactory trackHttpSolrMetrics; | ||
|
||
HttpSolrClientProvider(UpdateShardHandlerConfig cfg, SolrMetricsContext parentContext) { | ||
trackHttpSolrMetrics = new InstrumentedHttpListenerFactory(getNameStrategy(cfg)); | ||
initializeMetrics(parentContext); | ||
|
||
Http2SolrClient.Builder httpClientBuilder = | ||
new Http2SolrClient.Builder().withListenerFactory(List.of(trackHttpSolrMetrics)); | ||
this.httpClientBuilder = new Http2SolrClient.Builder().addListenerFactory(trackHttpSolrMetrics); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name httpSolrClientBuilder or similar |
||
|
||
if (cfg != null) { | ||
httpClientBuilder | ||
|
@@ -76,7 +76,7 @@ Http2SolrClient getSolrClient() { | |
} | ||
|
||
void setSecurityBuilder(HttpClientBuilderPlugin builder) { | ||
builder.setup(httpSolrClient); | ||
builder.setup(httpClientBuilder, httpSolrClient); | ||
} | ||
|
||
@Override | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,4 +34,8 @@ public interface HttpClientBuilderPlugin { | |
public SolrHttpClientBuilder getHttpClientBuilder(SolrHttpClientBuilder builder); | ||
|
||
public default void setup(Http2SolrClient client) {} | ||
|
||
public default void setup(Http2SolrClient.Builder httpClientBuilder, Http2SolrClient client) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe these should be split up; setup a client and builder separately (2 methods)? Feels weird to take both in setup(). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I agree separate methods would be nicer. But the implementing classes do things on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you point me at such so I can appreciate the problem better? |
||
setup(client); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -374,8 +374,17 @@ PublicKey fetchPublicKeyFromRemote(String nodename) { | |
} | ||
} | ||
|
||
@Override | ||
public void setup(Http2SolrClient.Builder httpClientBuilder, Http2SolrClient client) { | ||
setup(client, httpClientBuilder); | ||
} | ||
|
||
@Override | ||
public void setup(Http2SolrClient client) { | ||
setup(client, null); | ||
} | ||
|
||
private void setup(Http2SolrClient client, Http2SolrClient.Builder builder) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why have this separate and with different parameter order? In other words, lets make this one the |
||
final HttpListenerFactory.RequestResponseListener listener = | ||
new HttpListenerFactory.RequestResponseListener() { | ||
private static final String CACHED_REQUEST_USER_KEY = "cachedRequestUser"; | ||
|
@@ -431,7 +440,12 @@ private Optional<String> getUserFromJettyRequest(Request request) { | |
(String) request.getAttributes().get(CACHED_REQUEST_USER_KEY)); | ||
} | ||
}; | ||
client.addListenerFactory(() -> listener); | ||
if (client != null) { | ||
client.addListenerFactory(() -> listener); | ||
} | ||
if (builder != null) { | ||
builder.addListenerFactory(() -> listener); | ||
} | ||
} | ||
|
||
@Override | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,9 +40,8 @@ | |
public class CloudHttp2SolrClient extends CloudSolrClient { | ||
|
||
private final ClusterStateProvider stateProvider; | ||
private final LBHttp2SolrClient<Http2SolrClient> lbClient; | ||
private final LBHttp2SolrClient<Http2SolrClient.Builder> lbClient; | ||
private final Http2SolrClient myClient; | ||
private final boolean clientIsInternal; | ||
|
||
/** | ||
* Create a new client object that connects to Zookeeper and is always aware of the SolrCloud | ||
|
@@ -54,8 +53,8 @@ public class CloudHttp2SolrClient extends CloudSolrClient { | |
*/ | ||
protected CloudHttp2SolrClient(Builder builder) { | ||
super(builder.shardLeadersOnly, builder.parallelUpdates, builder.directUpdatesToLeadersOnly); | ||
this.clientIsInternal = builder.httpClient == null; | ||
this.myClient = createOrGetHttpClientFromBuilder(builder); | ||
var httpClientBuilder = createOrGetHttpClientBuilder(builder); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. httpSolrClientBuilder |
||
this.myClient = httpClientBuilder.build(); | ||
this.stateProvider = createClusterStateProvider(builder); | ||
this.retryExpiryTimeNano = builder.retryExpiryTimeNano; | ||
this.defaultCollection = builder.defaultCollection; | ||
|
@@ -73,16 +72,14 @@ protected CloudHttp2SolrClient(Builder builder) { | |
// locks. | ||
this.locks = objectList(builder.parallelCacheRefreshesLocks); | ||
|
||
this.lbClient = new LBHttp2SolrClient.Builder<Http2SolrClient>(myClient).build(); | ||
this.lbClient = new LBHttp2SolrClient.Builder<>(httpClientBuilder).build(); | ||
} | ||
|
||
private Http2SolrClient createOrGetHttpClientFromBuilder(Builder builder) { | ||
if (builder.httpClient != null) { | ||
return builder.httpClient; | ||
} else if (builder.internalClientBuilder != null) { | ||
return builder.internalClientBuilder.build(); | ||
private Http2SolrClient.Builder createOrGetHttpClientBuilder(Builder builder) { | ||
if (builder.internalClientBuilder != null) { | ||
return builder.internalClientBuilder; | ||
} else { | ||
return new Http2SolrClient.Builder().build(); | ||
return new Http2SolrClient.Builder(); | ||
} | ||
} | ||
|
||
|
@@ -129,7 +126,7 @@ private ClusterStateProvider createHttp2ClusterStateProvider( | |
|
||
private void closeMyClientIfNeeded() { | ||
try { | ||
if (clientIsInternal && myClient != null) { | ||
if (myClient != null) { | ||
myClient.close(); | ||
} | ||
} catch (Exception e) { | ||
|
@@ -148,7 +145,7 @@ public void close() throws IOException { | |
} | ||
|
||
@Override | ||
public LBHttp2SolrClient<Http2SolrClient> getLbClient() { | ||
public LBHttp2SolrClient<Http2SolrClient.Builder> getLbClient() { | ||
return lbClient; | ||
} | ||
|
||
|
@@ -171,7 +168,6 @@ public static class Builder { | |
protected Collection<String> zkHosts = new ArrayList<>(); | ||
protected List<String> solrUrls = new ArrayList<>(); | ||
protected String zkChroot; | ||
protected Http2SolrClient httpClient; | ||
protected boolean shardLeadersOnly = true; | ||
protected boolean directUpdatesToLeadersOnly = false; | ||
protected boolean parallelUpdates = true; | ||
|
@@ -404,23 +400,6 @@ public Builder withCollectionCacheTtl(long timeToLive, TimeUnit unit) { | |
return this; | ||
} | ||
|
||
/** | ||
* Set the internal http client. | ||
* | ||
* <p>Note: closing the httpClient instance is at the responsibility of the caller. | ||
* | ||
* @param httpClient http client | ||
* @return this | ||
*/ | ||
public Builder withHttpClient(Http2SolrClient httpClient) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure we want to take this away from users There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the most controversial part of this PR, and I do not want to merge a potentially disruptive API change like this without buy-in. I do not think this is much of a burden though, because the Builder has The purpose of forcing this is that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
which still exists, so if a user somehow has a client but not a builder but needs one due to the API change you introduce, they have this option.
Well written James! +1 |
||
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 | ||
|
@@ -430,10 +409,6 @@ public Builder withHttpClient(Http2SolrClient httpClient) { | |
* @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; | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -140,9 +140,7 @@ protected Http2SolrClient(String serverBaseUrl, Builder builder) { | |||||
this.httpClient = createHttpClient(builder); | ||||||
this.closeClient = true; | ||||||
} | ||||||
if (builder.listenerFactory != null) { | ||||||
this.listenerFactory.addAll(builder.listenerFactory); | ||||||
} | ||||||
this.listenerFactory.addAll(builder.listenerFactories); | ||||||
updateDefaultMimeTypeForParser(); | ||||||
|
||||||
this.httpClient.setFollowRedirects(Boolean.TRUE.equals(builder.followRedirects)); | ||||||
|
@@ -571,6 +569,7 @@ public final <R extends SolrResponse> R requestWithBaseUrl( | |||||
* @param clientFunction a Function that consumes a Http2SolrClient and returns an arbitrary value | ||||||
* @return the value returned after invoking 'clientFunction' | ||||||
* @param <R> the type returned by the provided function (and by this method) | ||||||
* @lucene.experimental | ||||||
*/ | ||||||
public <R> R requestWithBaseUrl( | ||||||
String baseUrl, SolrClientFunction<Http2SolrClient, R> clientFunction) | ||||||
|
@@ -906,7 +905,7 @@ public static class Builder | |||||
|
||||||
protected Long keyStoreReloadIntervalSecs; | ||||||
|
||||||
private List<HttpListenerFactory> listenerFactory; | ||||||
private List<HttpListenerFactory> listenerFactories = new ArrayList<>(0); | ||||||
|
||||||
public Builder() { | ||||||
super(); | ||||||
|
@@ -932,8 +931,27 @@ public Builder(String baseSolrUrl) { | |||||
this.baseSolrUrl = baseSolrUrl; | ||||||
} | ||||||
|
||||||
public Http2SolrClient.Builder withListenerFactory(List<HttpListenerFactory> listenerFactory) { | ||||||
this.listenerFactory = listenerFactory; | ||||||
/** | ||||||
* specify a listener factory, which will be appened to any existing values. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
* | ||||||
* @param listenerFactory a HttpListenerFactory | ||||||
* @return This Builder | ||||||
*/ | ||||||
public Http2SolrClient.Builder addListenerFactory(HttpListenerFactory listenerFactory) { | ||||||
this.listenerFactories.add(listenerFactory); | ||||||
return this; | ||||||
} | ||||||
|
||||||
/** | ||||||
* Specify listener factories, which will replace any existing values. | ||||||
* | ||||||
* @param listenerFactories a list of HttpListenerFactory instances | ||||||
* @return This Builder | ||||||
*/ | ||||||
public Http2SolrClient.Builder withListenerFactories( | ||||||
List<HttpListenerFactory> listenerFactories) { | ||||||
this.listenerFactories.clear(); | ||||||
this.listenerFactories.addAll(listenerFactories); | ||||||
return this; | ||||||
} | ||||||
|
||||||
|
@@ -1109,9 +1127,9 @@ public Builder withHttpClient(Http2SolrClient http2SolrClient) { | |||||
if (this.urlParamNames == null) { | ||||||
this.urlParamNames = http2SolrClient.urlParamNames; | ||||||
} | ||||||
if (this.listenerFactory == null) { | ||||||
this.listenerFactory = new ArrayList<HttpListenerFactory>(); | ||||||
http2SolrClient.listenerFactory.forEach(this.listenerFactory::add); | ||||||
if (this.listenerFactories.isEmpty()) { | ||||||
this.listenerFactories.clear(); | ||||||
http2SolrClient.listenerFactory.forEach(this.listenerFactories::add); | ||||||
} | ||||||
if (this.executor == null) { | ||||||
this.executor = http2SolrClient.executor; | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, should have a name like "solrClientBuilder" (maybe adding "http") to clarify this is building a SolrClient not an HttpClient.