Skip to content

Commit ff09c82

Browse files
authored
REST high-level client: add clear cache API (#28866)
* REST high-level client: add clear cache API Relates to #27205 Also Closes #26947 (rest-spec were outdated)
1 parent 52a517e commit ff09c82

File tree

11 files changed

+620
-117
lines changed

11 files changed

+620
-117
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
2525
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
2626
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
27+
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
28+
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
2729
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
2830
import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
2931
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
@@ -259,6 +261,29 @@ public void flushAsync(FlushRequest flushRequest, ActionListener<FlushResponse>
259261
listener, emptySet(), headers);
260262
}
261263

264+
/**
265+
* Clears the cache of one or more indices using the Clear Cache API
266+
* <p>
267+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clearcache.html">
268+
* Clear Cache API on elastic.co</a>
269+
*/
270+
public ClearIndicesCacheResponse clearCache(ClearIndicesCacheRequest clearIndicesCacheRequest, Header... headers) throws IOException {
271+
return restHighLevelClient.performRequestAndParseEntity(clearIndicesCacheRequest, Request::clearCache,
272+
ClearIndicesCacheResponse::fromXContent, emptySet(), headers);
273+
}
274+
275+
/**
276+
* Asynchronously clears the cache of one or more indices using the Clear Cache API
277+
* <p>
278+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-clearcache.html">
279+
* Clear Cache API on elastic.co</a>
280+
*/
281+
public void clearCacheAsync(ClearIndicesCacheRequest clearIndicesCacheRequest, ActionListener<ClearIndicesCacheResponse> listener,
282+
Header... headers) {
283+
restHighLevelClient.performRequestAsyncAndParseEntity(clearIndicesCacheRequest, Request::clearCache,
284+
ClearIndicesCacheResponse::fromXContent, listener, emptySet(), headers);
285+
}
286+
262287
/**
263288
* Checks if the index (indices) exists or not.
264289
* <p>

client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java

Lines changed: 98 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
3333
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
3434
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
35+
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
3536
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
3637
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
3738
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
@@ -170,13 +171,10 @@ static Request openIndex(OpenIndexRequest openIndexRequest) {
170171

171172
static Request closeIndex(CloseIndexRequest closeIndexRequest) {
172173
String endpoint = endpoint(closeIndexRequest.indices(), "_close");
173-
174174
Params parameters = Params.builder();
175-
176175
parameters.withTimeout(closeIndexRequest.timeout());
177176
parameters.withMasterTimeout(closeIndexRequest.masterNodeTimeout());
178177
parameters.withIndicesOptions(closeIndexRequest.indicesOptions());
179-
180178
return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null);
181179
}
182180

@@ -218,21 +216,35 @@ static Request putMapping(PutMappingRequest putMappingRequest) throws IOExceptio
218216
}
219217

220218
static Request refresh(RefreshRequest refreshRequest) {
221-
String endpoint = endpoint(refreshRequest.indices(), "_refresh");
219+
String[] indices = refreshRequest.indices() == null ? Strings.EMPTY_ARRAY : refreshRequest.indices();
220+
String endpoint = endpoint(indices, "_refresh");
222221
Params parameters = Params.builder();
223222
parameters.withIndicesOptions(refreshRequest.indicesOptions());
224223
return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null);
225224
}
226225

227226
static Request flush(FlushRequest flushRequest) {
228-
String endpoint = endpoint(flushRequest.indices(), "_flush");
227+
String[] indices = flushRequest.indices() == null ? Strings.EMPTY_ARRAY : flushRequest.indices();
228+
String endpoint = endpoint(indices, "_flush");
229229
Params parameters = Params.builder();
230230
parameters.withIndicesOptions(flushRequest.indicesOptions());
231231
parameters.putParam("wait_if_ongoing", Boolean.toString(flushRequest.waitIfOngoing()));
232232
parameters.putParam("force", Boolean.toString(flushRequest.force()));
233233
return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null);
234234
}
235235

236+
static Request clearCache(ClearIndicesCacheRequest clearIndicesCacheRequest) {
237+
String[] indices = clearIndicesCacheRequest.indices() == null ? Strings.EMPTY_ARRAY :clearIndicesCacheRequest.indices();
238+
String endpoint = endpoint(indices, "_cache/clear");
239+
Params parameters = Params.builder();
240+
parameters.withIndicesOptions(clearIndicesCacheRequest.indicesOptions());
241+
parameters.putParam("query", Boolean.toString(clearIndicesCacheRequest.queryCache()));
242+
parameters.putParam("fielddata", Boolean.toString(clearIndicesCacheRequest.fieldDataCache()));
243+
parameters.putParam("request", Boolean.toString(clearIndicesCacheRequest.requestCache()));
244+
parameters.putParam("fields", String.join(",", clearIndicesCacheRequest.fields()));
245+
return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null);
246+
}
247+
236248
static Request info() {
237249
return new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null);
238250
}
@@ -508,10 +520,13 @@ static Request existsAlias(GetAliasesRequest getAliasesRequest) {
508520
Params params = Params.builder();
509521
params.withIndicesOptions(getAliasesRequest.indicesOptions());
510522
params.withLocal(getAliasesRequest.local());
511-
if (getAliasesRequest.indices().length == 0 && getAliasesRequest.aliases().length == 0) {
523+
if ((getAliasesRequest.indices() == null || getAliasesRequest.indices().length == 0) &&
524+
(getAliasesRequest.aliases() == null || getAliasesRequest.aliases().length == 0)) {
512525
throw new IllegalArgumentException("existsAlias requires at least an alias or an index");
513526
}
514-
String endpoint = endpoint(getAliasesRequest.indices(), "_alias", getAliasesRequest.aliases());
527+
String[] indices = getAliasesRequest.indices() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.indices();
528+
String[] aliases = getAliasesRequest.aliases() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.aliases();
529+
String endpoint = endpoint(indices, "_alias", aliases);
515530
return new Request(HttpHead.METHOD_NAME, endpoint, params.getParams(), null);
516531
}
517532

@@ -540,8 +555,9 @@ private static Request resize(ResizeRequest resizeRequest) throws IOException {
540555
params.withTimeout(resizeRequest.timeout());
541556
params.withMasterTimeout(resizeRequest.masterNodeTimeout());
542557
params.withWaitForActiveShards(resizeRequest.getTargetIndexRequest().waitForActiveShards());
543-
String endpoint = buildEndpoint(resizeRequest.getSourceIndex(), "_" + resizeRequest.getResizeType().name().toLowerCase(Locale.ROOT),
544-
resizeRequest.getTargetIndexRequest().index());
558+
String endpoint = new EndpointBuilder().addPathPart(resizeRequest.getSourceIndex())
559+
.addPathPartAsIs("_" + resizeRequest.getResizeType().name().toLowerCase(Locale.ROOT))
560+
.addPathPart(resizeRequest.getTargetIndexRequest().index()).build();
545561
HttpEntity entity = createEntity(resizeRequest, REQUEST_BODY_CONTENT_TYPE);
546562
return new Request(HttpPut.METHOD_NAME, endpoint, params.getParams(), entity);
547563
}
@@ -551,10 +567,8 @@ static Request clusterPutSettings(ClusterUpdateSettingsRequest clusterUpdateSett
551567
parameters.withFlatSettings(clusterUpdateSettingsRequest.flatSettings());
552568
parameters.withTimeout(clusterUpdateSettingsRequest.timeout());
553569
parameters.withMasterTimeout(clusterUpdateSettingsRequest.masterNodeTimeout());
554-
555-
String endpoint = buildEndpoint("_cluster", "settings");
556570
HttpEntity entity = createEntity(clusterUpdateSettingsRequest, REQUEST_BODY_CONTENT_TYPE);
557-
return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity);
571+
return new Request(HttpPut.METHOD_NAME, "/_cluster/settings", parameters.getParams(), entity);
558572
}
559573

560574
static Request rollover(RolloverRequest rolloverRequest) throws IOException {
@@ -565,64 +579,60 @@ static Request rollover(RolloverRequest rolloverRequest) throws IOException {
565579
if (rolloverRequest.isDryRun()) {
566580
params.putParam("dry_run", Boolean.TRUE.toString());
567581
}
568-
String endpoint = buildEndpoint(rolloverRequest.getAlias(), "_rollover", rolloverRequest.getNewIndexName());
582+
String endpoint = new EndpointBuilder().addPathPart(rolloverRequest.getAlias()).addPathPartAsIs("_rollover")
583+
.addPathPart(rolloverRequest.getNewIndexName()).build();
569584
HttpEntity entity = createEntity(rolloverRequest, REQUEST_BODY_CONTENT_TYPE);
570585
return new Request(HttpPost.METHOD_NAME, endpoint, params.getParams(), entity);
571586
}
572587

588+
static Request indicesExist(GetIndexRequest request) {
589+
//this can be called with no indices as argument by transport client, not via REST though
590+
if (request.indices() == null || request.indices().length == 0) {
591+
throw new IllegalArgumentException("indices are mandatory");
592+
}
593+
String endpoint = endpoint(request.indices(), "");
594+
Params params = Params.builder();
595+
params.withLocal(request.local());
596+
params.withHuman(request.humanReadable());
597+
params.withIndicesOptions(request.indicesOptions());
598+
params.withFlatSettings(request.flatSettings());
599+
params.withIncludeDefaults(request.includeDefaults());
600+
return new Request(HttpHead.METHOD_NAME, endpoint, params.getParams(), null);
601+
}
602+
573603
private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException {
574604
BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef();
575605
return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));
576606
}
577607

578608
static String endpoint(String index, String type, String id) {
579-
return buildEndpoint(index, type, id);
609+
return new EndpointBuilder().addPathPart(index, type, id).build();
580610
}
581611

582612
static String endpoint(String index, String type, String id, String endpoint) {
583-
return buildEndpoint(index, type, id, endpoint);
613+
return new EndpointBuilder().addPathPart(index, type, id).addPathPartAsIs(endpoint).build();
584614
}
585615

586616
static String endpoint(String[] indices) {
587-
return buildEndpoint(String.join(",", indices));
617+
return new EndpointBuilder().addCommaSeparatedPathParts(indices).build();
588618
}
589619

590620
static String endpoint(String[] indices, String endpoint) {
591-
return buildEndpoint(String.join(",", indices), endpoint);
621+
return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint).build();
592622
}
593623

594624
static String endpoint(String[] indices, String[] types, String endpoint) {
595-
return buildEndpoint(String.join(",", indices), String.join(",", types), endpoint);
625+
return new EndpointBuilder().addCommaSeparatedPathParts(indices).addCommaSeparatedPathParts(types)
626+
.addPathPartAsIs(endpoint).build();
596627
}
597628

598629
static String endpoint(String[] indices, String endpoint, String[] suffixes) {
599-
return buildEndpoint(String.join(",", indices), endpoint, String.join(",", suffixes));
630+
return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint)
631+
.addCommaSeparatedPathParts(suffixes).build();
600632
}
601633

602634
static String endpoint(String[] indices, String endpoint, String type) {
603-
return endpoint(String.join(",", indices), endpoint, type);
604-
}
605-
606-
/**
607-
* Utility method to build request's endpoint given its parts as strings
608-
*/
609-
static String buildEndpoint(String... parts) {
610-
StringJoiner joiner = new StringJoiner("/", "/", "");
611-
for (String part : parts) {
612-
if (Strings.hasLength(part)) {
613-
try {
614-
//encode each part (e.g. index, type and id) separately before merging them into the path
615-
//we prepend "/" to the path part to make this pate absolute, otherwise there can be issues with
616-
//paths that start with `-` or contain `:`
617-
URI uri = new URI(null, null, null, -1, "/" + part, null, null);
618-
//manually encode any slash that each part may contain
619-
joiner.add(uri.getRawPath().substring(1).replaceAll("/", "%2F"));
620-
} catch (URISyntaxException e) {
621-
throw new IllegalArgumentException("Path part [" + part + "] couldn't be encoded", e);
622-
}
623-
}
624-
}
625-
return joiner.toString();
635+
return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint).addPathPart(type).build();
626636
}
627637

628638
/**
@@ -636,17 +646,6 @@ public static ContentType createContentType(final XContentType xContentType) {
636646
return ContentType.create(xContentType.mediaTypeWithoutParameters(), (Charset) null);
637647
}
638648

639-
static Request indicesExist(GetIndexRequest request) {
640-
String endpoint = endpoint(request.indices(), Strings.EMPTY_ARRAY, "");
641-
Params params = Params.builder();
642-
params.withLocal(request.local());
643-
params.withHuman(request.humanReadable());
644-
params.withIndicesOptions(request.indicesOptions());
645-
params.withFlatSettings(request.flatSettings());
646-
params.withIncludeDefaults(request.includeDefaults());
647-
return new Request(HttpHead.METHOD_NAME, endpoint, params.getParams(), null);
648-
}
649-
650649
/**
651650
* Utility class to build request's parameters map and centralize all parameter names.
652651
*/
@@ -852,4 +851,50 @@ static XContentType enforceSameContentType(IndexRequest indexRequest, @Nullable
852851
}
853852
return xContentType;
854853
}
854+
855+
/**
856+
* Utility class to build request's endpoint given its parts as strings
857+
*/
858+
static class EndpointBuilder {
859+
860+
private final StringJoiner joiner = new StringJoiner("/", "/", "");
861+
862+
EndpointBuilder addPathPart(String... parts) {
863+
for (String part : parts) {
864+
if (Strings.hasLength(part)) {
865+
joiner.add(encodePart(part));
866+
}
867+
}
868+
return this;
869+
}
870+
871+
EndpointBuilder addCommaSeparatedPathParts(String[] parts) {
872+
addPathPart(String.join(",", parts));
873+
return this;
874+
}
875+
876+
EndpointBuilder addPathPartAsIs(String part) {
877+
if (Strings.hasLength(part)) {
878+
joiner.add(part);
879+
}
880+
return this;
881+
}
882+
883+
String build() {
884+
return joiner.toString();
885+
}
886+
887+
private static String encodePart(String pathPart) {
888+
try {
889+
//encode each part (e.g. index, type and id) separately before merging them into the path
890+
//we prepend "/" to the path part to make this pate absolute, otherwise there can be issues with
891+
//paths that start with `-` or contain `:`
892+
URI uri = new URI(null, null, null, -1, "/" + pathPart, null, null);
893+
//manually encode any slash that each part may contain
894+
return uri.getRawPath().substring(1).replaceAll("/", "%2F");
895+
} catch (URISyntaxException e) {
896+
throw new IllegalArgumentException("Path part [" + pathPart + "] couldn't be encoded", e);
897+
}
898+
}
899+
}
855900
}

client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
2929
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
3030
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
31+
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
32+
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse;
3133
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
3234
import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
3335
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
@@ -431,9 +433,36 @@ public void testFlush() throws IOException {
431433
{
432434
String nonExistentIndex = "non_existent_index";
433435
assertFalse(indexExists(nonExistentIndex));
434-
FlushRequest refreshRequest = new FlushRequest(nonExistentIndex);
436+
FlushRequest flushRequest = new FlushRequest(nonExistentIndex);
435437
ElasticsearchException exception = expectThrows(ElasticsearchException.class,
436-
() -> execute(refreshRequest, highLevelClient().indices()::flush, highLevelClient().indices()::flushAsync));
438+
() -> execute(flushRequest, highLevelClient().indices()::flush, highLevelClient().indices()::flushAsync));
439+
assertEquals(RestStatus.NOT_FOUND, exception.status());
440+
}
441+
}
442+
443+
public void testClearCache() throws IOException {
444+
{
445+
String index = "index";
446+
Settings settings = Settings.builder()
447+
.put("number_of_shards", 1)
448+
.put("number_of_replicas", 0)
449+
.build();
450+
createIndex(index, settings);
451+
ClearIndicesCacheRequest clearCacheRequest = new ClearIndicesCacheRequest(index);
452+
ClearIndicesCacheResponse clearCacheResponse =
453+
execute(clearCacheRequest, highLevelClient().indices()::clearCache, highLevelClient().indices()::clearCacheAsync);
454+
assertThat(clearCacheResponse.getTotalShards(), equalTo(1));
455+
assertThat(clearCacheResponse.getSuccessfulShards(), equalTo(1));
456+
assertThat(clearCacheResponse.getFailedShards(), equalTo(0));
457+
assertThat(clearCacheResponse.getShardFailures(), equalTo(BroadcastResponse.EMPTY));
458+
}
459+
{
460+
String nonExistentIndex = "non_existent_index";
461+
assertFalse(indexExists(nonExistentIndex));
462+
ClearIndicesCacheRequest clearCacheRequest = new ClearIndicesCacheRequest(nonExistentIndex);
463+
ElasticsearchException exception = expectThrows(ElasticsearchException.class,
464+
() -> execute(clearCacheRequest, highLevelClient().indices()::clearCache,
465+
highLevelClient().indices()::clearCacheAsync));
437466
assertEquals(RestStatus.NOT_FOUND, exception.status());
438467
}
439468
}

0 commit comments

Comments
 (0)