parent
303ce30f77
commit
95dea2408d
|
@ -37,6 +37,8 @@ import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
|||
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
|
||||
|
||||
|
@ -215,6 +217,26 @@ public final class IndicesClient {
|
|||
listener, emptySet(), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh one or more indices using the Refresh API
|
||||
* <p>
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html"> Refresh API on elastic.co</a>
|
||||
*/
|
||||
public RefreshResponse refresh(RefreshRequest refreshRequest, Header... headers) throws IOException {
|
||||
return restHighLevelClient.performRequestAndParseEntity(refreshRequest, Request::refresh, RefreshResponse::fromXContent,
|
||||
emptySet(), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously refresh one or more indices using the Refresh API
|
||||
* <p>
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html"> Refresh API on elastic.co</a>
|
||||
*/
|
||||
public void refreshAsync(RefreshRequest refreshRequest, ActionListener<RefreshResponse> listener, Header... headers) {
|
||||
restHighLevelClient.performRequestAsyncAndParseEntity(refreshRequest, Request::refresh, RefreshResponse::fromXContent,
|
||||
listener, emptySet(), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the index (indices) exists or not.
|
||||
* <p>
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
|||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
|
||||
|
@ -216,6 +217,15 @@ public final class Request {
|
|||
return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity);
|
||||
}
|
||||
|
||||
static Request refresh(RefreshRequest refreshRequest) {
|
||||
String endpoint = endpoint(refreshRequest.indices(), "_refresh");
|
||||
|
||||
Params parameters = Params.builder();
|
||||
parameters.withIndicesOptions(refreshRequest.indicesOptions());
|
||||
|
||||
return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null);
|
||||
}
|
||||
|
||||
static Request info() {
|
||||
return new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
|||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
|
@ -47,6 +49,7 @@ import org.elasticsearch.action.admin.indices.shrink.ResizeType;
|
|||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
|
@ -381,6 +384,32 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
|
|||
assertEquals(RestStatus.NOT_FOUND, exception.status());
|
||||
}
|
||||
|
||||
public void testRefresh() throws IOException {
|
||||
{
|
||||
String index = "index";
|
||||
Settings settings = Settings.builder()
|
||||
.put("number_of_shards", 1)
|
||||
.put("number_of_replicas", 0)
|
||||
.build();
|
||||
createIndex(index, settings);
|
||||
RefreshRequest refreshRequest = new RefreshRequest(index);
|
||||
RefreshResponse refreshResponse =
|
||||
execute(refreshRequest, highLevelClient().indices()::refresh, highLevelClient().indices()::refreshAsync);
|
||||
assertThat(refreshResponse.getTotalShards(), equalTo(1));
|
||||
assertThat(refreshResponse.getSuccessfulShards(), equalTo(1));
|
||||
assertThat(refreshResponse.getFailedShards(), equalTo(0));
|
||||
assertThat(refreshResponse.getShardFailures(), equalTo(BroadcastResponse.EMPTY));
|
||||
}
|
||||
{
|
||||
String nonExistentIndex = "non_existent_index";
|
||||
assertFalse(indexExists(nonExistentIndex));
|
||||
RefreshRequest refreshRequest = new RefreshRequest(nonExistentIndex);
|
||||
ElasticsearchException exception = expectThrows(ElasticsearchException.class,
|
||||
() -> execute(refreshRequest, highLevelClient().indices()::refresh, highLevelClient().indices()::refreshAsync));
|
||||
assertEquals(RestStatus.NOT_FOUND, exception.status());
|
||||
}
|
||||
}
|
||||
|
||||
public void testExistsAlias() throws IOException {
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest("alias");
|
||||
assertFalse(execute(getAliasesRequest, highLevelClient().indices()::existsAlias, highLevelClient().indices()::existsAliasAsync));
|
||||
|
@ -495,4 +524,4 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
|
|||
assertEquals("test_new", rolloverResponse.getNewIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
|||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
|
||||
|
@ -535,6 +536,21 @@ public class RequestTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testRefresh() {
|
||||
String[] indices = randomIndicesNames(1, 5);
|
||||
RefreshRequest refreshRequest = new RefreshRequest(indices);
|
||||
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
setRandomIndicesOptions(refreshRequest::indicesOptions, refreshRequest::indicesOptions, expectedParams);
|
||||
|
||||
Request request = Request.refresh(refreshRequest);
|
||||
StringJoiner endpoint = new StringJoiner("/", "/", "").add(String.join(",", indices)).add("_refresh");
|
||||
assertThat(endpoint.toString(), equalTo(request.getEndpoint()));
|
||||
assertThat(request.getParameters(), equalTo(expectedParams));
|
||||
assertThat(request.getEntity(), nullValue());
|
||||
assertThat(request.getMethod(), equalTo(HttpPost.METHOD_NAME));
|
||||
}
|
||||
|
||||
public void testUpdate() throws IOException {
|
||||
XContentType xContentType = randomFrom(XContentType.values());
|
||||
|
||||
|
@ -1058,7 +1074,7 @@ public class RequestTests extends ESTestCase {
|
|||
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> Request.existsAlias(getAliasesRequest));
|
||||
assertEquals("existsAlias requires at least an alias or an index", iae.getMessage());
|
||||
}
|
||||
|
||||
|
||||
public void testRankEval() throws Exception {
|
||||
RankEvalSpec spec = new RankEvalSpec(
|
||||
Collections.singletonList(new RatedRequest("queryId", Collections.emptyList(), new SearchSourceBuilder())),
|
||||
|
@ -1130,7 +1146,7 @@ public class RequestTests extends ESTestCase {
|
|||
assertEquals(expectedParams, request.getParameters());
|
||||
assertToXContentBody(resizeRequest, request.getEntity());
|
||||
}
|
||||
|
||||
|
||||
public void testClusterPutSettings() throws IOException {
|
||||
ClusterUpdateSettingsRequest request = new ClusterUpdateSettingsRequest();
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
|
|
|
@ -38,12 +38,15 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
|||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
|
||||
import org.elasticsearch.action.support.ActiveShardCount;
|
||||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
|
@ -620,6 +623,74 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
|
|||
}
|
||||
}
|
||||
|
||||
public void testRefreshIndex() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
{
|
||||
createIndex("index1", Settings.EMPTY);
|
||||
}
|
||||
|
||||
{
|
||||
// tag::refresh-request
|
||||
RefreshRequest request = new RefreshRequest("index1"); // <1>
|
||||
RefreshRequest requestMultiple = new RefreshRequest("index1", "index2"); // <2>
|
||||
RefreshRequest requestAll = new RefreshRequest(); // <3>
|
||||
// end::refresh-request
|
||||
|
||||
// tag::refresh-request-indicesOptions
|
||||
request.indicesOptions(IndicesOptions.lenientExpandOpen()); // <1>
|
||||
// end::refresh-request-indicesOptions
|
||||
|
||||
// tag::refresh-execute
|
||||
RefreshResponse refreshResponse = client.indices().refresh(request);
|
||||
// end::refresh-execute
|
||||
|
||||
// tag::refresh-response
|
||||
int totalShards = refreshResponse.getTotalShards(); // <1>
|
||||
int successfulShards = refreshResponse.getSuccessfulShards(); // <2>
|
||||
int failedShards = refreshResponse.getFailedShards(); // <3>
|
||||
DefaultShardOperationFailedException[] failures = refreshResponse.getShardFailures(); // <4>
|
||||
// end::refresh-response
|
||||
|
||||
// tag::refresh-execute-listener
|
||||
ActionListener<RefreshResponse> listener = new ActionListener<RefreshResponse>() {
|
||||
@Override
|
||||
public void onResponse(RefreshResponse refreshResponse) {
|
||||
// <1>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
// <2>
|
||||
}
|
||||
};
|
||||
// end::refresh-execute-listener
|
||||
|
||||
// Replace the empty listener by a blocking listener in test
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
listener = new LatchedActionListener<>(listener, latch);
|
||||
|
||||
// tag::refresh-execute-async
|
||||
client.indices().refreshAsync(request, listener); // <1>
|
||||
// end::refresh-execute-async
|
||||
|
||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
{
|
||||
// tag::refresh-notfound
|
||||
try {
|
||||
RefreshRequest request = new RefreshRequest("does_not_exist");
|
||||
client.indices().refresh(request);
|
||||
} catch (ElasticsearchException exception) {
|
||||
if (exception.status() == RestStatus.NOT_FOUND) {
|
||||
// <1>
|
||||
}
|
||||
}
|
||||
// end::refresh-notfound
|
||||
}
|
||||
}
|
||||
|
||||
public void testCloseIndex() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
[[java-rest-high-refresh]]
|
||||
=== Refresh API
|
||||
|
||||
[[java-rest-high-refresh-request]]
|
||||
==== Refresh Request
|
||||
|
||||
A `RefreshRequest` can be applied to one or more indices, or even on `_all` the indices:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[refresh-request]
|
||||
--------------------------------------------------
|
||||
<1> Refresh one index
|
||||
<2> Refresh multiple indices
|
||||
<3> Refresh all the indices
|
||||
|
||||
==== Optional arguments
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[refresh-request-indicesOptions]
|
||||
--------------------------------------------------
|
||||
<1> Setting `IndicesOptions` controls how unavailable indices are resolved and
|
||||
how wildcard expressions are expanded
|
||||
|
||||
[[java-rest-high-refresh-sync]]
|
||||
==== Synchronous Execution
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[refresh-execute]
|
||||
--------------------------------------------------
|
||||
|
||||
[[java-rest-high-refresh-async]]
|
||||
==== Asynchronous Execution
|
||||
|
||||
The asynchronous execution of a refresh request requires both the `RefreshRequest`
|
||||
instance and an `ActionListener` instance to be passed to the asynchronous
|
||||
method:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[refresh-execute-async]
|
||||
--------------------------------------------------
|
||||
<1> The `RefreshRequest` to execute and the `ActionListener` to use when
|
||||
the execution completes
|
||||
|
||||
The asynchronous method does not block and returns immediately. Once it is
|
||||
completed the `ActionListener` is called back using the `onResponse` method
|
||||
if the execution successfully completed or using the `onFailure` method if
|
||||
it failed.
|
||||
|
||||
A typical listener for `RefreshResponse` looks like:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[refresh-execute-listener]
|
||||
--------------------------------------------------
|
||||
<1> Called when the execution is successfully completed. The response is
|
||||
provided as an argument
|
||||
<2> Called in case of failure. The raised exception is provided as an argument
|
||||
|
||||
[[java-rest-high-refresh-response]]
|
||||
==== Refresh Response
|
||||
|
||||
The returned `RefreshResponse` allows to retrieve information about the
|
||||
executed operation as follows:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[refresh-response]
|
||||
--------------------------------------------------
|
||||
<1> Total number of shards hit by the refresh request
|
||||
<2> Number of shards where the refresh has succeeded
|
||||
<3> Number of shards where the refresh has failed
|
||||
<4> A list of failures if the operation failed on one or more shards
|
||||
|
||||
By default, if the indices were not found, an `ElasticsearchException` will be thrown:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[refresh-notfound]
|
||||
--------------------------------------------------
|
||||
<1> Do something if the indices to be refreshed were not found
|
|
@ -52,6 +52,7 @@ Index Management::
|
|||
* <<java-rest-high-close-index>>
|
||||
* <<java-rest-high-shrink-index>>
|
||||
* <<java-rest-high-split-index>>
|
||||
* <<java-rest-high-refresh>>
|
||||
* <<java-rest-high-rollover-index>>
|
||||
|
||||
Mapping Management::
|
||||
|
@ -68,6 +69,7 @@ include::indices/open_index.asciidoc[]
|
|||
include::indices/close_index.asciidoc[]
|
||||
include::indices/shrink_index.asciidoc[]
|
||||
include::indices/split_index.asciidoc[]
|
||||
include::indices/refresh.asciidoc[]
|
||||
include::indices/rollover.asciidoc[]
|
||||
include::indices/put_mapping.asciidoc[]
|
||||
include::indices/update_aliases.asciidoc[]
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.elasticsearch.action.admin.indices.refresh;
|
||||
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastRequest;
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,10 @@ package org.elasticsearch.action.admin.indices.refresh;
|
|||
|
||||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -29,10 +32,25 @@ import java.util.List;
|
|||
*/
|
||||
public class RefreshResponse extends BroadcastResponse {
|
||||
|
||||
private static final ConstructingObjectParser<RefreshResponse, Void> PARSER = new ConstructingObjectParser<>("refresh", true,
|
||||
arg -> {
|
||||
BroadcastResponse response = (BroadcastResponse) arg[0];
|
||||
return new RefreshResponse(response.getTotalShards(), response.getSuccessfulShards(), response.getFailedShards(),
|
||||
Arrays.asList(response.getShardFailures()));
|
||||
});
|
||||
|
||||
static {
|
||||
declareBroadcastFields(PARSER);
|
||||
}
|
||||
|
||||
RefreshResponse() {
|
||||
}
|
||||
|
||||
RefreshResponse(int totalShards, int successfulShards, int failedShards, List<DefaultShardOperationFailedException> shardFailures) {
|
||||
super(totalShards, successfulShards, failedShards, shardFailures);
|
||||
}
|
||||
|
||||
public static RefreshResponse fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,17 +22,36 @@ package org.elasticsearch.action.support;
|
|||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.ExceptionsHelper.detailedMessage;
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
|
||||
public class DefaultShardOperationFailedException implements ShardOperationFailedException {
|
||||
|
||||
private static final String INDEX = "index";
|
||||
private static final String SHARD_ID = "shard";
|
||||
private static final String REASON = "reason";
|
||||
|
||||
private static final ConstructingObjectParser<DefaultShardOperationFailedException, Void> PARSER = new ConstructingObjectParser<>(
|
||||
"failures", true, arg -> new DefaultShardOperationFailedException((String) arg[0], (int) arg[1] ,(Throwable) arg[2]));
|
||||
|
||||
static {
|
||||
PARSER.declareString(constructorArg(), new ParseField(INDEX));
|
||||
PARSER.declareInt(constructorArg(), new ParseField(SHARD_ID));
|
||||
PARSER.declareObject(constructorArg(), (p, c) -> ElasticsearchException.fromXContent(p), new ParseField(REASON));
|
||||
}
|
||||
|
||||
private String index;
|
||||
|
||||
private int shardId;
|
||||
|
@ -45,8 +64,10 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile
|
|||
}
|
||||
|
||||
public DefaultShardOperationFailedException(ElasticsearchException e) {
|
||||
this.index = e.getIndex() == null ? null : e.getIndex().getName();
|
||||
this.shardId = e.getShardId().id();
|
||||
Index index = e.getIndex();
|
||||
this.index = index == null ? null : index.getName();
|
||||
ShardId shardId = e.getShardId();
|
||||
this.shardId = shardId == null ? -1 : shardId.id();
|
||||
this.reason = e;
|
||||
this.status = e.status();
|
||||
}
|
||||
|
@ -123,12 +144,14 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile
|
|||
builder.field("index", index());
|
||||
builder.field("status", status.name());
|
||||
if (reason != null) {
|
||||
builder.field("reason");
|
||||
builder.startObject();
|
||||
builder.startObject("reason");
|
||||
ElasticsearchException.generateThrowableXContent(builder, params, reason);
|
||||
builder.endObject();
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static DefaultShardOperationFailedException fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,25 +21,51 @@ package org.elasticsearch.action.support.broadcast;
|
|||
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContentFragment;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.RestActions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.action.support.DefaultShardOperationFailedException.readShardOperationFailed;
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
|
||||
|
||||
/**
|
||||
* Base class for all broadcast operation based responses.
|
||||
*/
|
||||
public class BroadcastResponse extends ActionResponse {
|
||||
private static final DefaultShardOperationFailedException[] EMPTY = new DefaultShardOperationFailedException[0];
|
||||
public class BroadcastResponse extends ActionResponse implements ToXContentFragment {
|
||||
|
||||
public static final DefaultShardOperationFailedException[] EMPTY = new DefaultShardOperationFailedException[0];
|
||||
|
||||
private static final ParseField _SHARDS_FIELD = new ParseField("_shards");
|
||||
private static final ParseField TOTAL_FIELD = new ParseField("total");
|
||||
private static final ParseField SUCCESSFUL_FIELD = new ParseField("successful");
|
||||
private static final ParseField FAILED_FIELD = new ParseField("failed");
|
||||
private static final ParseField FAILURES_FIELD = new ParseField("failures");
|
||||
|
||||
private int totalShards;
|
||||
private int successfulShards;
|
||||
private int failedShards;
|
||||
private DefaultShardOperationFailedException[] shardFailures = EMPTY;
|
||||
|
||||
protected static <T extends BroadcastResponse> void declareBroadcastFields(ConstructingObjectParser<T, Void> PARSER) {
|
||||
ConstructingObjectParser<BroadcastResponse, Void> shardsParser = new ConstructingObjectParser<>("_shards", true,
|
||||
arg -> new BroadcastResponse((int) arg[0], (int) arg[1], (int) arg[2], (List<DefaultShardOperationFailedException>) arg[3]));
|
||||
shardsParser.declareInt(constructorArg(), TOTAL_FIELD);
|
||||
shardsParser.declareInt(constructorArg(), SUCCESSFUL_FIELD);
|
||||
shardsParser.declareInt(constructorArg(), FAILED_FIELD);
|
||||
shardsParser.declareObjectArray(optionalConstructorArg(),
|
||||
(p, c) -> DefaultShardOperationFailedException.fromXContent(p), FAILURES_FIELD);
|
||||
PARSER.declareObject(constructorArg(), shardsParser, _SHARDS_FIELD);
|
||||
}
|
||||
|
||||
public BroadcastResponse() {
|
||||
}
|
||||
|
||||
|
@ -120,4 +146,10 @@ public class BroadcastResponse extends ActionResponse {
|
|||
exp.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
RestActions.buildBroadcastShardsHeader(builder, params, this);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ import java.io.IOException;
|
|||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.action.RestActions.buildBroadcastShardsHeader;
|
||||
|
||||
public class RestRefreshAction extends BaseRestHandler {
|
||||
public RestRefreshAction(Settings settings, RestController controller) {
|
||||
|
@ -62,7 +61,7 @@ public class RestRefreshAction extends BaseRestHandler {
|
|||
@Override
|
||||
public RestResponse buildResponse(RefreshResponse response, XContentBuilder builder) throws Exception {
|
||||
builder.startObject();
|
||||
buildBroadcastShardsHeader(builder, request, response);
|
||||
response.toXContent(builder, request);
|
||||
builder.endObject();
|
||||
return new BytesRestResponse(response.getStatus(), builder);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.admin.indices.refresh;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.test.XContentTestUtils.insertRandomFields;
|
||||
import static org.hamcrest.CoreMatchers.anyOf;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
||||
public class RefreshResponseTests extends ESTestCase {
|
||||
|
||||
public void testToXContent() {
|
||||
RefreshResponse response = new RefreshResponse(10, 10, 0, null);
|
||||
String output = Strings.toString(response);
|
||||
assertEquals("{\"_shards\":{\"total\":10,\"successful\":10,\"failed\":0}}", output);
|
||||
}
|
||||
|
||||
public void testToAndFromXContent() throws IOException {
|
||||
doFromXContentTestWithRandomFields(false);
|
||||
}
|
||||
|
||||
public void testFromXContentWithRandomFields() throws IOException {
|
||||
doFromXContentTestWithRandomFields(true);
|
||||
}
|
||||
|
||||
public void testFailuresDeduplication() throws IOException {
|
||||
List<DefaultShardOperationFailedException> failures = new ArrayList<>();
|
||||
Index index = new Index("test", "_na_");
|
||||
ElasticsearchException exception1 = new ElasticsearchException("foo", new IllegalArgumentException("bar"));
|
||||
exception1.setIndex(index);
|
||||
exception1.setShard(new ShardId(index, 0));
|
||||
ElasticsearchException exception2 = new ElasticsearchException("foo", new IllegalArgumentException("bar"));
|
||||
exception2.setIndex(index);
|
||||
exception2.setShard(new ShardId(index, 1));
|
||||
ElasticsearchException exception3 = new ElasticsearchException("fizz", new IllegalStateException("buzz"));
|
||||
exception3.setIndex(index);
|
||||
exception3.setShard(new ShardId(index, 2));
|
||||
failures.add(new DefaultShardOperationFailedException(exception1));
|
||||
failures.add(new DefaultShardOperationFailedException(exception2));
|
||||
failures.add(new DefaultShardOperationFailedException(exception3));
|
||||
|
||||
RefreshResponse response = new RefreshResponse(10, 7, 3, failures);
|
||||
boolean humanReadable = randomBoolean();
|
||||
XContentType xContentType = randomFrom(XContentType.values());
|
||||
BytesReference bytesReference = toShuffledXContent(response, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
|
||||
RefreshResponse parsedResponse;
|
||||
try(XContentParser parser = createParser(xContentType.xContent(), bytesReference)) {
|
||||
parsedResponse = RefreshResponse.fromXContent(parser);
|
||||
assertNull(parser.nextToken());
|
||||
}
|
||||
|
||||
assertThat(parsedResponse.getShardFailures().length, equalTo(2));
|
||||
DefaultShardOperationFailedException[] parsedFailures = parsedResponse.getShardFailures();
|
||||
assertThat(parsedFailures[0].index(), equalTo("test"));
|
||||
assertThat(parsedFailures[0].shardId(), anyOf(equalTo(0), equalTo(1)));
|
||||
assertThat(parsedFailures[0].status(), equalTo(RestStatus.INTERNAL_SERVER_ERROR));
|
||||
assertThat(parsedFailures[0].getCause().getMessage(), containsString("foo"));
|
||||
assertThat(parsedFailures[1].index(), equalTo("test"));
|
||||
assertThat(parsedFailures[1].shardId(), equalTo(2));
|
||||
assertThat(parsedFailures[1].status(), equalTo(RestStatus.INTERNAL_SERVER_ERROR));
|
||||
assertThat(parsedFailures[1].getCause().getMessage(), containsString("fizz"));
|
||||
|
||||
ToXContent.Params params = new ToXContent.MapParams(Collections.singletonMap("group_shard_failures", "false"));
|
||||
BytesReference bytesReferenceWithoutDedup = toShuffledXContent(response, xContentType, params, humanReadable);
|
||||
try(XContentParser parser = createParser(xContentType.xContent(), bytesReferenceWithoutDedup)) {
|
||||
parsedResponse = RefreshResponse.fromXContent(parser);
|
||||
assertNull(parser.nextToken());
|
||||
}
|
||||
|
||||
assertThat(parsedResponse.getShardFailures().length, equalTo(3));
|
||||
parsedFailures = parsedResponse.getShardFailures();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (i < 2) {
|
||||
assertThat(parsedFailures[i].index(), equalTo("test"));
|
||||
assertThat(parsedFailures[i].shardId(), equalTo(i));
|
||||
assertThat(parsedFailures[i].status(), equalTo(RestStatus.INTERNAL_SERVER_ERROR));
|
||||
assertThat(parsedFailures[i].getCause().getMessage(), containsString("foo"));
|
||||
} else {
|
||||
assertThat(parsedFailures[i].index(), equalTo("test"));
|
||||
assertThat(parsedFailures[i].shardId(), equalTo(i));
|
||||
assertThat(parsedFailures[i].status(), equalTo(RestStatus.INTERNAL_SERVER_ERROR));
|
||||
assertThat(parsedFailures[i].getCause().getMessage(), containsString("fizz"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doFromXContentTestWithRandomFields(boolean addRandomFields) throws IOException {
|
||||
RefreshResponse response = createTestItem(10);
|
||||
boolean humanReadable = randomBoolean();
|
||||
XContentType xContentType = randomFrom(XContentType.values());
|
||||
BytesReference bytesReference = toShuffledXContent(response, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
|
||||
if (addRandomFields) {
|
||||
bytesReference = insertRandomFields(xContentType, bytesReference, null, random());
|
||||
}
|
||||
RefreshResponse parsedResponse;
|
||||
try(XContentParser parser = createParser(xContentType.xContent(), bytesReference)) {
|
||||
parsedResponse = RefreshResponse.fromXContent(parser);
|
||||
assertNull(parser.nextToken());
|
||||
}
|
||||
|
||||
assertThat(response.getTotalShards(), equalTo(parsedResponse.getTotalShards()));
|
||||
assertThat(response.getSuccessfulShards(), equalTo(parsedResponse.getSuccessfulShards()));
|
||||
assertThat(response.getFailedShards(), equalTo(parsedResponse.getFailedShards()));
|
||||
assertFailureEquals(response.getShardFailures(), parsedResponse.getShardFailures());
|
||||
}
|
||||
|
||||
private static void assertFailureEquals(DefaultShardOperationFailedException[] original,
|
||||
DefaultShardOperationFailedException[] parsedback) {
|
||||
assertThat(original.length, equalTo(parsedback.length));
|
||||
for (int i = 0; i < original.length; i++) {
|
||||
assertThat(original[i].index(), equalTo(parsedback[i].index()));
|
||||
assertThat(original[i].shardId(), equalTo(parsedback[i].shardId()));
|
||||
assertThat(original[i].status(), equalTo(parsedback[i].status()));
|
||||
assertThat(parsedback[i].getCause().getMessage(), containsString(original[i].getCause().getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private static RefreshResponse createTestItem(int totalShards) {
|
||||
List<DefaultShardOperationFailedException> failures = null;
|
||||
int successfulShards = randomInt(totalShards);
|
||||
int failedShards = totalShards - successfulShards;
|
||||
if (failedShards > 0) {
|
||||
failures = new ArrayList<>();
|
||||
for (int i = 0; i < failedShards; i++) {
|
||||
ElasticsearchException exception = new ElasticsearchException("exception message " + i);
|
||||
exception.setIndex(new Index("index" + i, "_na_"));
|
||||
exception.setShard(new ShardId("index" + i, "_na_", i));
|
||||
if (randomBoolean()) {
|
||||
failures.add(new DefaultShardOperationFailedException(exception));
|
||||
} else {
|
||||
failures.add(new DefaultShardOperationFailedException("index" + i, i, new Exception("exception message " + i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new RefreshResponse(totalShards, successfulShards, failedShards, failures);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.support;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.xcontent.XContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DefaultShardOperationFailedExceptionTests extends ESTestCase {
|
||||
|
||||
public void testToString() {
|
||||
{
|
||||
DefaultShardOperationFailedException exception = new DefaultShardOperationFailedException(
|
||||
new ElasticsearchException("foo", new IllegalArgumentException("bar", new RuntimeException("baz"))));
|
||||
assertEquals("[null][-1] failed, reason [ElasticsearchException[foo]; nested: " +
|
||||
"IllegalArgumentException[bar]; nested: RuntimeException[baz]; ]", exception.toString());
|
||||
}
|
||||
{
|
||||
ElasticsearchException elasticsearchException = new ElasticsearchException("foo");
|
||||
elasticsearchException.setIndex(new Index("index1", "_na_"));
|
||||
elasticsearchException.setShard(new ShardId("index1", "_na_", 1));
|
||||
DefaultShardOperationFailedException exception = new DefaultShardOperationFailedException(elasticsearchException);
|
||||
assertEquals("[index1][1] failed, reason [ElasticsearchException[foo]]", exception.toString());
|
||||
}
|
||||
{
|
||||
DefaultShardOperationFailedException exception = new DefaultShardOperationFailedException("index2", 2, new Exception("foo"));
|
||||
assertEquals("[index2][2] failed, reason [Exception[foo]]", exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void testToXContent() throws IOException {
|
||||
{
|
||||
DefaultShardOperationFailedException exception = new DefaultShardOperationFailedException(new ElasticsearchException("foo"));
|
||||
assertEquals("{\"shard\":-1,\"index\":null,\"status\":\"INTERNAL_SERVER_ERROR\"," +
|
||||
"\"reason\":{\"type\":\"exception\",\"reason\":\"foo\"}}", Strings.toString(exception));
|
||||
}
|
||||
{
|
||||
DefaultShardOperationFailedException exception = new DefaultShardOperationFailedException(
|
||||
new ElasticsearchException("foo", new IllegalArgumentException("bar")));
|
||||
assertEquals("{\"shard\":-1,\"index\":null,\"status\":\"INTERNAL_SERVER_ERROR\",\"reason\":{\"type\":\"exception\"," +
|
||||
"\"reason\":\"foo\",\"caused_by\":{\"type\":\"illegal_argument_exception\",\"reason\":\"bar\"}}}",
|
||||
Strings.toString(exception));
|
||||
}
|
||||
{
|
||||
DefaultShardOperationFailedException exception = new DefaultShardOperationFailedException(
|
||||
new BroadcastShardOperationFailedException(new ShardId("test", "_uuid", 2), "foo", new IllegalStateException("bar")));
|
||||
assertEquals("{\"shard\":2,\"index\":\"test\",\"status\":\"INTERNAL_SERVER_ERROR\"," +
|
||||
"\"reason\":{\"type\":\"illegal_state_exception\",\"reason\":\"bar\"}}", Strings.toString(exception));
|
||||
}
|
||||
{
|
||||
DefaultShardOperationFailedException exception = new DefaultShardOperationFailedException("test", 1,
|
||||
new IllegalArgumentException("foo"));
|
||||
assertEquals("{\"shard\":1,\"index\":\"test\",\"status\":\"BAD_REQUEST\"," +
|
||||
"\"reason\":{\"type\":\"illegal_argument_exception\",\"reason\":\"foo\"}}", Strings.toString(exception));
|
||||
}
|
||||
}
|
||||
|
||||
public void testFromXContent() throws IOException {
|
||||
XContent xContent = randomFrom(XContentType.values()).xContent();
|
||||
XContentBuilder builder = XContentBuilder.builder(xContent)
|
||||
.startObject()
|
||||
.field("shard", 1)
|
||||
.field("index", "test")
|
||||
.field("status", "INTERNAL_SERVER_ERROR")
|
||||
.startObject("reason")
|
||||
.field("type", "exception")
|
||||
.field("reason", "foo")
|
||||
.endObject()
|
||||
.endObject();
|
||||
builder = shuffleXContent(builder);
|
||||
DefaultShardOperationFailedException parsed;
|
||||
try(XContentParser parser = createParser(xContent, builder.bytes())) {
|
||||
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
|
||||
parsed = DefaultShardOperationFailedException.fromXContent(parser);
|
||||
assertEquals(XContentParser.Token.END_OBJECT, parser.currentToken());
|
||||
assertNull(parser.nextToken());
|
||||
}
|
||||
|
||||
assertNotNull(parsed);
|
||||
assertEquals(parsed.shardId(), 1);
|
||||
assertEquals(parsed.index(), "test");
|
||||
assertEquals(parsed.status(), RestStatus.INTERNAL_SERVER_ERROR);
|
||||
assertEquals(parsed.getCause().getMessage(), "Elasticsearch exception [type=exception, reason=foo]");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue