Convert ElasticRestClientBuilder to a provider

Convert to a provider so that we only have one instance of the
client which is initialized once.

Change-Id: I4747114e28ea9a509fb86350713a7736a3becd44
This commit is contained in:
David Pursehouse
2018-05-30 10:33:47 +09:00
parent 473f53b2f4
commit c07dc94665
7 changed files with 67 additions and 26 deletions

View File

@@ -47,7 +47,6 @@ import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity; import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.client.Response; import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
abstract class AbstractElasticIndex<K, V> implements Index<K, V> { abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
protected static final String BULK = "_bulk"; protected static final String BULK = "_bulk";
@@ -81,7 +80,7 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
private final Schema<V> schema; private final Schema<V> schema;
private final SitePaths sitePaths; private final SitePaths sitePaths;
private final String indexNameRaw; private final String indexNameRaw;
private final RestClient client; private final ElasticRestClientProvider client;
protected final String indexName; protected final String indexName;
protected final Gson gson; protected final Gson gson;
@@ -91,7 +90,7 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
ElasticConfiguration cfg, ElasticConfiguration cfg,
SitePaths sitePaths, SitePaths sitePaths,
Schema<V> schema, Schema<V> schema,
ElasticRestClientBuilder clientBuilder, ElasticRestClientProvider client,
String indexName) { String indexName) {
this.sitePaths = sitePaths; this.sitePaths = sitePaths;
this.schema = schema; this.schema = schema;
@@ -99,7 +98,7 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
this.queryBuilder = new ElasticQueryBuilder(); this.queryBuilder = new ElasticQueryBuilder();
this.indexName = cfg.getIndexName(indexName, schema.getVersion()); this.indexName = cfg.getIndexName(indexName, schema.getVersion());
this.indexNameRaw = indexName; this.indexNameRaw = indexName;
this.client = clientBuilder.build(); this.client = client;
} }
@Override @Override
@@ -109,11 +108,7 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
@Override @Override
public void close() { public void close() {
try { // Do nothing. Client is closed by the provider.
client.close();
} catch (IOException e) {
// Ignored.
}
} }
@Override @Override
@@ -135,10 +130,10 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
@Override @Override
public void deleteAll() throws IOException { public void deleteAll() throws IOException {
// Delete the index, if it exists. // Delete the index, if it exists.
Response response = client.performRequest("HEAD", indexName); Response response = client.get().performRequest("HEAD", indexName);
int statusCode = response.getStatusLine().getStatusCode(); int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) { if (statusCode == HttpStatus.SC_OK) {
response = client.performRequest("DELETE", indexName); response = client.get().performRequest("DELETE", indexName);
statusCode = response.getStatusLine().getStatusCode(); statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) { if (statusCode != HttpStatus.SC_OK) {
throw new IOException( throw new IOException(
@@ -209,6 +204,6 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
String method, Object payload, String uri, Map<String, String> params) throws IOException { String method, Object payload, String uri, Map<String, String> params) throws IOException {
String payloadStr = payload instanceof String ? (String) payload : payload.toString(); String payloadStr = payload instanceof String ? (String) payload : payload.toString();
HttpEntity entity = new NStringEntity(payloadStr, ContentType.APPLICATION_JSON); HttpEntity entity = new NStringEntity(payloadStr, ContentType.APPLICATION_JSON);
return client.performRequest(method, uri, params, entity); return client.get().performRequest(method, uri, params, entity);
} }
} }

View File

@@ -79,9 +79,9 @@ public class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, Accoun
ElasticConfiguration cfg, ElasticConfiguration cfg,
SitePaths sitePaths, SitePaths sitePaths,
Provider<AccountCache> accountCache, Provider<AccountCache> accountCache,
ElasticRestClientBuilder clientBuilder, ElasticRestClientProvider client,
@Assisted Schema<AccountState> schema) { @Assisted Schema<AccountState> schema) {
super(cfg, sitePaths, schema, clientBuilder, ACCOUNTS); super(cfg, sitePaths, schema, client, ACCOUNTS);
this.accountCache = accountCache; this.accountCache = accountCache;
this.mapping = new AccountMapping(schema); this.mapping = new AccountMapping(schema);
this.schema = schema; this.schema = schema;

View File

@@ -110,9 +110,9 @@ public class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeDa
ChangeData.Factory changeDataFactory, ChangeData.Factory changeDataFactory,
FillArgs fillArgs, FillArgs fillArgs,
SitePaths sitePaths, SitePaths sitePaths,
ElasticRestClientBuilder clientBuilder, ElasticRestClientProvider client,
@Assisted Schema<ChangeData> schema) { @Assisted Schema<ChangeData> schema) {
super(cfg, sitePaths, schema, clientBuilder, CHANGES); super(cfg, sitePaths, schema, client, CHANGES);
this.db = db; this.db = db;
this.changeDataFactory = changeDataFactory; this.changeDataFactory = changeDataFactory;
this.fillArgs = fillArgs; this.fillArgs = fillArgs;

View File

@@ -76,9 +76,9 @@ public class ElasticGroupIndex extends AbstractElasticIndex<AccountGroup.UUID, A
ElasticConfiguration cfg, ElasticConfiguration cfg,
SitePaths sitePaths, SitePaths sitePaths,
Provider<GroupCache> groupCache, Provider<GroupCache> groupCache,
ElasticRestClientBuilder clientBuilder, ElasticRestClientProvider client,
@Assisted Schema<AccountGroup> schema) { @Assisted Schema<AccountGroup> schema) {
super(cfg, sitePaths, schema, clientBuilder, GROUPS); super(cfg, sitePaths, schema, client, GROUPS);
this.groupCache = groupCache; this.groupCache = groupCache;
this.mapping = new GroupMapping(schema); this.mapping = new GroupMapping(schema);
this.schema = schema; this.schema = schema;

View File

@@ -36,6 +36,12 @@ public class ElasticIndexModule extends AbstractIndexModule {
super(singleVersions, threads); super(singleVersions, threads);
} }
@Override
public void configure() {
super.configure();
install(ElasticRestClientProvider.module());
}
@Override @Override
protected Class<? extends AccountIndex> getAccountIndex() { protected Class<? extends AccountIndex> getAccountIndex() {
return ElasticAccountIndex.class; return ElasticAccountIndex.class;

View File

@@ -25,20 +25,19 @@ import java.util.List;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.elasticsearch.client.Response; import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
@Singleton @Singleton
class ElasticIndexVersionDiscovery { class ElasticIndexVersionDiscovery {
private final RestClient client; private final ElasticRestClientProvider client;
@Inject @Inject
ElasticIndexVersionDiscovery(ElasticRestClientBuilder clientBuilder) { ElasticIndexVersionDiscovery(ElasticRestClientProvider client) {
this.client = clientBuilder.build(); this.client = client;
} }
List<String> discover(String prefix, String indexName) throws IOException { List<String> discover(String prefix, String indexName) throws IOException {
String name = prefix + indexName + "_"; String name = prefix + indexName + "_";
Response response = client.performRequest(HttpGet.METHOD_NAME, name + "*/_aliases"); Response response = client.get().performRequest(HttpGet.METHOD_NAME, name + "*/_aliases");
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return new JsonParser() return new JsonParser()

View File

@@ -14,8 +14,12 @@
package com.google.gerrit.elasticsearch; package com.google.gerrit.elasticsearch;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import java.io.IOException;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope; import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.auth.UsernamePasswordCredentials;
@@ -26,20 +30,57 @@ import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestClientBuilder;
@Singleton @Singleton
class ElasticRestClientBuilder { class ElasticRestClientProvider implements Provider<RestClient>, LifecycleListener {
private final HttpHost[] hosts; private final HttpHost[] hosts;
private final String username; private final String username;
private final String password; private final String password;
private RestClient client;
@Inject @Inject
ElasticRestClientBuilder(ElasticConfiguration cfg) { ElasticRestClientProvider(ElasticConfiguration cfg) {
hosts = cfg.urls.toArray(new HttpHost[cfg.urls.size()]); hosts = cfg.urls.toArray(new HttpHost[cfg.urls.size()]);
username = cfg.username; username = cfg.username;
password = cfg.password; password = cfg.password;
} }
RestClient build() { public static LifecycleModule module() {
return new LifecycleModule() {
@Override
protected void configure() {
listener().to(ElasticRestClientProvider.class);
}
};
}
@Override
public RestClient get() {
if (client == null) {
synchronized (this) {
if (client == null) {
client = build();
}
}
}
return client;
}
@Override
public void start() {}
@Override
public void stop() {
if (client != null) {
try {
client.close();
} catch (IOException e) {
// Ignore. We can't do anything about it.
}
}
}
private RestClient build() {
RestClientBuilder builder = RestClient.builder(hosts); RestClientBuilder builder = RestClient.builder(hosts);
setConfiguredCredentialsIfAny(builder); setConfiguredCredentialsIfAny(builder);
return builder.build(); return builder.build();