-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Add Refresh API for RestHighLevelClient #27799
Changes from 3 commits
e8efd85
6613822
77da3d5
1753a33
90756b9
a7cbc48
1e7c019
18086a3
ed89a7a
8ee43f8
7581273
0168ed5
7d4ec22
fa9cf77
9c03b74
9fc4529
364de26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,8 @@ | |
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; | ||
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 java.io.IOException; | ||
import java.util.Collections; | ||
|
@@ -111,4 +113,25 @@ public void openIndexAsync(OpenIndexRequest openIndexRequest, ActionListener<Ope | |
listener, Collections.emptySet(), headers); | ||
} | ||
|
||
/** | ||
* Refresh one or more index 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> | ||
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. Nit: it can fit on the same line as the link without exceeding 140 chars (Same for the async method too) |
||
*/ | ||
public final RefreshResponse refresh(RefreshRequest refreshRequest, Header... headers) throws IOException { | ||
return restHighLevelClient.performRequestAndParseEntity(refreshRequest, Request::refresh, RefreshResponse::fromXContent, | ||
Collections.emptySet(), headers); | ||
} | ||
|
||
/** | ||
* Asynchronously refresh one or more index 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 final void refreshAsync(RefreshRequest refreshRequest, ActionListener<RefreshResponse> listener, Header... headers) { | ||
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. you need to remove the final modifier from these tests. The class is already final, hence our checkstyle checks will fail with this redundant modifiers. You can check this out by running gradlew check from client/rest-high-level |
||
restHighLevelClient.performRequestAsyncAndParseEntity(refreshRequest, Request::refresh, RefreshResponse::fromXContent, | ||
listener, Collections.emptySet(), headers); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,22 +27,22 @@ | |
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; | ||
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.support.IndicesOptions; | ||
import org.elasticsearch.rest.RestStatus; | ||
|
||
import java.io.IOException; | ||
import java.util.Locale; | ||
|
||
import static org.hamcrest.Matchers.equalTo; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.common.xcontent.XContentBuilder; | ||
import org.elasticsearch.common.xcontent.XContentHelper; | ||
import org.elasticsearch.common.xcontent.XContentType; | ||
import org.elasticsearch.common.xcontent.json.JsonXContent; | ||
import org.elasticsearch.rest.RestStatus; | ||
|
||
import java.io.IOException; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
|
||
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS; | ||
import static org.hamcrest.Matchers.equalTo; | ||
|
||
public class IndicesClientIT extends ESRestHighLevelClientTestCase { | ||
|
||
|
@@ -180,6 +180,32 @@ public void testOpenNonExistentIndex() throws IOException { | |
assertEquals(RestStatus.NOT_FOUND, strictException.status()); | ||
} | ||
|
||
public void testRefresh() throws IOException { | ||
{ | ||
String[] indices = randomIndices(1, 5); | ||
for (String index : indices) { | ||
createIndex(index); | ||
} | ||
RefreshRequest refreshRequest = new RefreshRequest(indices); | ||
RefreshResponse refreshResponse = | ||
execute(refreshRequest, highLevelClient().indices()::refresh, highLevelClient().indices()::refreshAsync); | ||
// 10 shards per index by default | ||
assertThat(refreshResponse.getTotalShards(), equalTo(indices.length * 10)); | ||
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. shall we also check successful and failed? 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. Seems 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. sure I was asking if we can check successful and failed rather than only total. does that make sense? 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 also check that successful is greater than 0, failed is greater or equal to 0 and that successful + failed is equal to total? So that the test does not rely on a fixed number of shards and replicas? 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. In fact successful shards + failed shards not always equal to total shards because of unallocated shards. they are not included in failed shards, of course nor in successful shards. It depends on the test environment. I run it locally with a single machine and for an index all the replicas shards are not allocated. So this is why I didn't check it. Maybe we can check successful > 0, failed == 0 ? 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. thanks for the explanation, your proposal sounds good to me 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. Sounds good too |
||
} | ||
{ | ||
String[] nonExistentIndices = randomIndices(1, 5); | ||
for (String nonExistentIndex : nonExistentIndices) { | ||
if (indexExists(nonExistentIndex)) { | ||
return; | ||
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. That would ignore the end of the test. Instead you could simply execute a refresh with a unique "_does_not_exist" index? |
||
} | ||
} | ||
RefreshRequest refreshRequest = new RefreshRequest(nonExistentIndices); | ||
ElasticsearchException exception = expectThrows(ElasticsearchException.class, | ||
() -> execute(refreshRequest, highLevelClient().indices()::refresh, highLevelClient().indices()::refreshAsync)); | ||
assertEquals(RestStatus.NOT_FOUND, exception.status()); | ||
} | ||
} | ||
|
||
private static String[] randomIndices(int minIndicesNum, int maxIndicesNum) { | ||
int numIndices = randomIntBetween(minIndicesNum, maxIndicesNum); | ||
String[] indices = new String[numIndices]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,18 +21,40 @@ | |
|
||
import org.elasticsearch.action.ShardOperationFailedException; | ||
import org.elasticsearch.action.support.broadcast.BroadcastResponse; | ||
import org.elasticsearch.common.ParseField; | ||
import org.elasticsearch.common.xcontent.ConstructingObjectParser; | ||
import org.elasticsearch.common.xcontent.ToXContentFragment; | ||
import org.elasticsearch.common.xcontent.XContentParser; | ||
|
||
import java.util.List; | ||
|
||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; | ||
|
||
/** | ||
* The response of a refresh action. | ||
*/ | ||
public class RefreshResponse extends BroadcastResponse { | ||
public class RefreshResponse extends BroadcastResponse implements ToXContentFragment { | ||
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. ToXContentFragment is not needed here as it has been added to BroadcastResponse |
||
|
||
private static final ConstructingObjectParser<RefreshResponse, Void> PARSER = new ConstructingObjectParser<>("refresh", | ||
true, arg -> (RefreshResponse) arg[0]); | ||
|
||
static { | ||
ConstructingObjectParser<RefreshResponse, Void> shardsParser = new ConstructingObjectParser<>("_shards", true, | ||
arg -> new RefreshResponse((int) arg[0], (int) arg[1], (int) arg[2], null)); | ||
shardsParser.declareInt(constructorArg(), new ParseField(Fields.TOTAL)); | ||
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. These fields belongs to BroadcastResponse so I think we could have something similar to CreateIndexResponse/AcknowledgedResponse? I mean only the delcaration of the static
and in What do you think? 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. Yeah, as these fields belong to |
||
shardsParser.declareInt(constructorArg(), new ParseField(Fields.SUCCESSFUL)); | ||
shardsParser.declareInt(constructorArg(), new ParseField(Fields.FAILED)); | ||
PARSER.declareObject(constructorArg(), shardsParser, new ParseField(Fields._SHARDS)); | ||
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. I think that we never print out nor parse back the shard failures. Should we rather do so? Looking at the current behaviour, I think that for this API we return an http error code (taken from the first shard failure) , yet we may not want to throw an exception in such but rather return a proper 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.
We do it (kind of) in I also don't like the fact 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. I've a quick look at what we have done in 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. yea we should do something similar. To make this feasible though we need #28312 to go in, so that it's enforced that only one type of exception needs to be parsed ( |
||
} | ||
|
||
RefreshResponse() { | ||
} | ||
|
||
RefreshResponse(int totalShards, int successfulShards, int failedShards, List<ShardOperationFailedException> shardFailures) { | ||
super(totalShards, successfulShards, failedShards, shardFailures); | ||
} | ||
|
||
public static RefreshResponse fromXContent(XContentParser parser) { | ||
return PARSER.apply(parser, null); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,8 +23,10 @@ | |
import org.elasticsearch.action.ShardOperationFailedException; | ||
import org.elasticsearch.common.io.stream.StreamInput; | ||
import org.elasticsearch.common.io.stream.StreamOutput; | ||
import org.elasticsearch.rest.RestStatus; | ||
import org.elasticsearch.common.xcontent.ToXContentFragment; | ||
import org.elasticsearch.common.xcontent.XContentBuilder; | ||
import org.elasticsearch.index.shard.ShardNotFoundException; | ||
import org.elasticsearch.rest.RestStatus; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
|
@@ -34,7 +36,7 @@ | |
/** | ||
* Base class for all broadcast operation based responses. | ||
*/ | ||
public class BroadcastResponse extends ActionResponse { | ||
public class BroadcastResponse extends ActionResponse implements ToXContentFragment{ | ||
private static final ShardOperationFailedException[] EMPTY = new ShardOperationFailedException[0]; | ||
private int totalShards; | ||
private int successfulShards; | ||
|
@@ -127,4 +129,21 @@ public void writeTo(StreamOutput out) throws IOException { | |
exp.writeTo(out); | ||
} | ||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
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. If we want to make BroadcastResponse implementing ToXContentFragment then we need to bring in the logic from 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 see that we have build 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. So you want to reuse RestActions.buildBroadcastShardsHeader() in RefreshResponse.toXContent() instead? 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. Hello @tlrx, srry for not having responded in time because I just want to see a bit more to discuss.I mean we don't need to make 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.
Don't be sorry at all! You're helping to build a better
Well, the But we need to test this fromXContent method and we have to be sure that a RefreshResponse object will always be generated the same way, in a way that can be parsed by the fromXContent method. We also try to be a bit lenient when we parse back the XContent so that it does not break when new fields are added or when fields are shuffled in the XContent. If you search for By having the XContent building logic in the |
||
builder.startObject(Fields._SHARDS); | ||
builder.field(Fields.TOTAL, getTotalShards()); | ||
builder.field(Fields.SUCCESSFUL, getSuccessfulShards()); | ||
builder.field(Fields.FAILED, getFailedShards()); | ||
builder.endObject(); | ||
return 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 not calling 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. It doesn't really matter if we just call 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. I see why we may not want to call 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 sounds good! |
||
} | ||
|
||
public static final class Fields { | ||
public static final String _SHARDS = "_shards"; | ||
public static final String TOTAL = "total"; | ||
public static final String SUCCESSFUL = "successful"; | ||
public static final String FAILED = "failed"; | ||
} | ||
} |
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.
Nit: one or more index -> one or more indices