Skip to content

Commit 1af0417

Browse files
authored
Async search: remove version from response (#53960)
The goal of the version field was to quickly show when you can expect to find something new in the search response, compared to when nothing has changed. This can also be done by looking at the `_shards` section and `num_reduce_phases` returned with the search response. In fact when there has been one or more additional reduction of the results, you can expect new results in the search response. Otherwise, the `_shards` section could notify of additional failures of shards that have completed the query, but that is not a guarantee that their results will be exposed (only when the following partial reduction is performed their results will be available). That said this commit clarifies this in the docs and removes the version field from the async search response
1 parent 2dc7950 commit 1af0417

File tree

8 files changed

+37
-81
lines changed

8 files changed

+37
-81
lines changed

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

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
public class AsyncSearchResponse implements ToXContentObject {
4242
@Nullable
4343
private final String id;
44-
private final int version;
4544
@Nullable
4645
private final SearchResponse searchResponse;
4746
@Nullable
@@ -55,15 +54,13 @@ public class AsyncSearchResponse implements ToXContentObject {
5554
/**
5655
* Creates an {@link AsyncSearchResponse} with the arguments that are always present in the server response
5756
*/
58-
AsyncSearchResponse(int version,
59-
boolean isPartial,
60-
boolean isRunning,
61-
long startTimeMillis,
62-
long expirationTimeMillis,
63-
@Nullable String id,
64-
@Nullable SearchResponse searchResponse,
65-
@Nullable ElasticsearchException error) {
66-
this.version = version;
57+
AsyncSearchResponse(boolean isPartial,
58+
boolean isRunning,
59+
long startTimeMillis,
60+
long expirationTimeMillis,
61+
@Nullable String id,
62+
@Nullable SearchResponse searchResponse,
63+
@Nullable ElasticsearchException error) {
6764
this.isPartial = isPartial;
6865
this.isRunning = isRunning;
6966
this.startTimeMillis = startTimeMillis;
@@ -81,13 +78,6 @@ public String getId() {
8178
return id;
8279
}
8380

84-
/**
85-
* Returns the version of this response.
86-
*/
87-
public int getVersion() {
88-
return version;
89-
}
90-
9181
/**
9282
* Returns the current {@link SearchResponse} or <code>null</code> if not available.
9383
*
@@ -145,7 +135,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
145135
if (id != null) {
146136
builder.field("id", id);
147137
}
148-
builder.field("version", version);
149138
builder.field("is_partial", isPartial);
150139
builder.field("is_running", isRunning);
151140
builder.field("start_time_in_millis", startTimeMillis);
@@ -165,7 +154,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
165154
}
166155

167156
public static final ParseField ID_FIELD = new ParseField("id");
168-
public static final ParseField VERSION_FIELD = new ParseField("version");
169157
public static final ParseField IS_PARTIAL_FIELD = new ParseField("is_partial");
170158
public static final ParseField IS_RUNNING_FIELD = new ParseField("is_running");
171159
public static final ParseField START_TIME_FIELD = new ParseField("start_time_in_millis");
@@ -176,16 +164,14 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
176164
public static final ConstructingObjectParser<AsyncSearchResponse, Void> PARSER = new ConstructingObjectParser<>(
177165
"submit_async_search_response", true,
178166
args -> new AsyncSearchResponse(
179-
(int) args[0],
167+
(boolean) args[0],
180168
(boolean) args[1],
181-
(boolean) args[2],
169+
(long) args[2],
182170
(long) args[3],
183-
(long) args[4],
184-
(String) args[5],
185-
(SearchResponse) args[6],
186-
(ElasticsearchException) args[7]));
171+
(String) args[4],
172+
(SearchResponse) args[5],
173+
(ElasticsearchException) args[6]));
187174
static {
188-
PARSER.declareInt(constructorArg(), VERSION_FIELD);
189175
PARSER.declareBoolean(constructorArg(), IS_PARTIAL_FIELD);
190176
PARSER.declareBoolean(constructorArg(), IS_RUNNING_FIELD);
191177
PARSER.declareLong(constructorArg(), START_TIME_FIELD);
@@ -203,7 +189,7 @@ private static SearchResponse parseSearchResponse(XContentParser p) throws IOExc
203189
return SearchResponse.innerFromXContent(p);
204190
}
205191

206-
public static AsyncSearchResponse fromXContent(XContentParser parser) throws IOException {
192+
public static AsyncSearchResponse fromXContent(XContentParser parser) {
207193
return PARSER.apply(parser, null);
208194
}
209195

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ public void testSubmitAsyncSearchRequest() throws IOException {
4040
// 15 sec should be enough to make sure we always complete right away
4141
request.setWaitForCompletion(new TimeValue(15, TimeUnit.SECONDS));
4242
AsyncSearchResponse response = highLevelClient().asyncSearch().submitAsyncSearch(request, RequestOptions.DEFAULT);
43-
assertTrue(response.getVersion() >= 0);
4443
assertFalse(response.isPartial());
4544
assertTrue(response.getStartTime() > 0);
4645
assertTrue(response.getExpirationTime() > 0);

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ public class AsyncSearchResponseTests
3636

3737
@Override
3838
protected org.elasticsearch.xpack.core.search.action.AsyncSearchResponse createServerTestInstance(XContentType xContentType) {
39-
int version = randomIntBetween(0, Integer.MAX_VALUE);
4039
boolean isPartial = randomBoolean();
4140
boolean isRunning = randomBoolean();
4241
long startTimeMillis = randomLongBetween(0, Long.MAX_VALUE);
@@ -48,7 +47,7 @@ protected org.elasticsearch.xpack.core.search.action.AsyncSearchResponse createS
4847
: new SearchResponse(InternalSearchResponse.empty(), randomAlphaOfLength(10), 1, 1, 0, randomIntBetween(0, 10000),
4948
ShardSearchFailure.EMPTY_ARRAY, Clusters.EMPTY);
5049
org.elasticsearch.xpack.core.search.action.AsyncSearchResponse testResponse =
51-
new org.elasticsearch.xpack.core.search.action.AsyncSearchResponse(id, version, searchResponse, error, isPartial, isRunning,
50+
new org.elasticsearch.xpack.core.search.action.AsyncSearchResponse(id, searchResponse, error, isPartial, isRunning,
5251
startTimeMillis, expirationTimeMillis);
5352
return testResponse;
5453
}
@@ -62,7 +61,6 @@ protected AsyncSearchResponse doParseToClientInstance(XContentParser parser) thr
6261
protected void assertInstances(org.elasticsearch.xpack.core.search.action.AsyncSearchResponse expected, AsyncSearchResponse parsed) {
6362
assertNotSame(parsed, expected);
6463
assertEquals(expected.getId(), parsed.getId());
65-
assertEquals(expected.getVersion(), parsed.getVersion());
6664
assertEquals(expected.isRunning(), parsed.isRunning());
6765
assertEquals(expected.isPartial(), parsed.isPartial());
6866
assertEquals(expected.getStartTime(), parsed.getStartTime());

docs/reference/search/async-search.asciidoc

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ results are returned as part of the <<search-api-response-body,`response`>> obje
4343
--------------------------------------------------
4444
{
4545
"id" : "FmRldE8zREVEUzA2ZVpUeGs2ejJFUFEaMkZ5QTVrSTZSaVN3WlNFVmtlWHJsdzoxMDc=", <1>
46-
"version" : 0,
4746
"is_partial" : true, <2>
4847
"is_running" : true, <3>
4948
"start_time_in_millis" : 1583945890986,
@@ -135,17 +134,16 @@ GET /_async_search/FmRldE8zREVEUzA2ZVpUeGs2ejJFUFEaMkZ5QTVrSTZSaVN3WlNFVmtlWHJsd
135134
--------------------------------------------------
136135
{
137136
"id" : "FmRldE8zREVEUzA2ZVpUeGs2ejJFUFEaMkZ5QTVrSTZSaVN3WlNFVmtlWHJsdzoxMDc=",
138-
"version" : 2, <1>
139-
"is_partial" : true, <2>
140-
"is_running" : true, <3>
137+
"is_partial" : true, <1>
138+
"is_running" : true, <2>
141139
"start_time_in_millis" : 1583945890986,
142-
"expiration_time_in_millis" : 1584377890986, <4>
140+
"expiration_time_in_millis" : 1584377890986, <3>
143141
"response" : {
144142
"took" : 12144,
145143
"timed_out" : false,
146-
"num_reduce_phases" : 38,
144+
"num_reduce_phases" : 38, <4>
147145
"_shards" : {
148-
"total" : 562,
146+
"total" : 562, <5>
149147
"successful" : 188,
150148
"skipped" : 0,
151149
"failed" : 0
@@ -158,7 +156,7 @@ GET /_async_search/FmRldE8zREVEUzA2ZVpUeGs2ejJFUFEaMkZ5QTVrSTZSaVN3WlNFVmtlWHJsd
158156
"max_score" : null,
159157
"hits" : [ ]
160158
},
161-
"aggregations" : { <5>
159+
"aggregations" : { <6>
162160
"sale_date" : {
163161
"buckets" : []
164162
}
@@ -178,15 +176,16 @@ GET /_async_search/FmRldE8zREVEUzA2ZVpUeGs2ejJFUFEaMkZ5QTVrSTZSaVN3WlNFVmtlWHJsd
178176
// TESTRESPONSE[s/"buckets" : \[\]/"buckets": $body.response.aggregations.sale_date.buckets/]
179177
// TESTRESPONSE[s/"num_reduce_phases" : 38,//]
180178

181-
<1> The returned `version` is useful to identify whether the response contains
182-
additional results compared to previously obtained responses. If the version
183-
stays the same, no new results have become available, otherwise a higher version
184-
number indicates that more shards have completed their execution of the query
185-
and their partial results are also included in the response.
186-
<2> Whether the returned search results are partial or final
187-
<3> Whether the search is still being executed or it has completed
188-
<4> When the async search will expire
189-
<5> Partial aggregations results, coming from the shards that have already
179+
<1> Whether the returned search results are partial or final
180+
<2> Whether the search is still being executed or it has completed
181+
<3> When the async search will expire
182+
<4> Indicates how many reduction of the results have been performed. If this
183+
number increases compared to the last retrieved results, you can expect
184+
additional results included in the search response
185+
<5> Indicates how many shards have executed the query. Note that in order for
186+
shard results to be included in the search response, they need to be reduced
187+
first.
188+
<6> Partial aggregations results, coming from the shards that have already
190189
completed the execution of the query.
191190

192191
The `wait_for_completion` parameter, which defaults to `1`, can also be provided

x-pack/plugin/async-search/src/main/java/org/elasticsearch/xpack/search/MutableSearchResponse.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ class MutableSearchResponse {
4040
private final AtomicArray<ShardSearchFailure> shardFailures;
4141
private final Supplier<InternalAggregation.ReduceContext> aggReduceContextSupplier;
4242

43-
private int version;
4443
private boolean isPartial;
4544
private boolean isFinalReduce;
4645
private int successfulShards;
@@ -63,7 +62,6 @@ class MutableSearchResponse {
6362
this.skippedShards = skippedShards;
6463
this.clusters = clusters;
6564
this.aggReduceContextSupplier = aggReduceContextSupplier;
66-
this.version = 0;
6765
this.shardFailures = totalShards == -1 ? null : new AtomicArray<>(totalShards-skippedShards);
6866
this.isPartial = true;
6967
this.sections = totalShards == -1 ? null : new InternalSearchResponse(
@@ -83,7 +81,6 @@ synchronized void updatePartialResponse(int successfulShards, SearchResponseSect
8381
throw new IllegalStateException("received partial response out of order: "
8482
+ newSections.getNumReducePhases() + " < " + sections.getNumReducePhases());
8583
}
86-
++ version;
8784
this.successfulShards = successfulShards;
8885
this.sections = newSections;
8986
this.isPartial = true;
@@ -96,7 +93,6 @@ synchronized void updatePartialResponse(int successfulShards, SearchResponseSect
9693
*/
9794
synchronized void updateFinalResponse(int successfulShards, SearchResponseSections newSections) {
9895
failIfFrozen();
99-
++ version;
10096
this.successfulShards = successfulShards;
10197
this.sections = newSections;
10298
this.isPartial = false;
@@ -110,7 +106,6 @@ synchronized void updateFinalResponse(int successfulShards, SearchResponseSectio
110106
*/
111107
synchronized void updateWithFailure(Exception exc) {
112108
failIfFrozen();
113-
++ version;
114109
this.isPartial = true;
115110
this.failure = ElasticsearchException.guessRootCauses(exc)[0];
116111
this.frozen = true;
@@ -147,7 +142,7 @@ synchronized AsyncSearchResponse toAsyncSearchResponse(AsyncSearchTask task, lon
147142
} else {
148143
resp = null;
149144
}
150-
return new AsyncSearchResponse(task.getSearchId().getEncoded(), version, resp, failure, isPartial,
145+
return new AsyncSearchResponse(task.getSearchId().getEncoded(), resp, failure, isPartial,
151146
frozen == false, task.getStartTime(), expirationTime);
152147
}
153148

@@ -159,7 +154,7 @@ private void failIfFrozen() {
159154

160155
private ShardSearchFailure[] buildShardFailures() {
161156
if (shardFailures == null) {
162-
return new ShardSearchFailure[0];
157+
return ShardSearchFailure.EMPTY_ARRAY;
163158
}
164159
List<ShardSearchFailure> failures = new ArrayList<>();
165160
for (int i = 0; i < shardFailures.length(); i++) {

x-pack/plugin/async-search/src/test/java/org/elasticsearch/xpack/search/AsyncSearchResponseTests.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,15 @@ static AsyncSearchResponse randomAsyncSearchResponse(String searchId, SearchResp
9191
int rand = randomIntBetween(0, 2);
9292
switch (rand) {
9393
case 0:
94-
return new AsyncSearchResponse(searchId, randomIntBetween(0, Integer.MAX_VALUE), randomBoolean(),
94+
return new AsyncSearchResponse(searchId, randomBoolean(),
9595
randomBoolean(), randomNonNegativeLong(), randomNonNegativeLong());
9696

9797
case 1:
98-
return new AsyncSearchResponse(searchId, randomIntBetween(0, Integer.MAX_VALUE), searchResponse, null,
98+
return new AsyncSearchResponse(searchId, searchResponse, null,
9999
randomBoolean(), randomBoolean(), randomNonNegativeLong(), randomNonNegativeLong());
100100

101101
case 2:
102-
return new AsyncSearchResponse(searchId, randomIntBetween(0, Integer.MAX_VALUE), searchResponse,
102+
return new AsyncSearchResponse(searchId, searchResponse,
103103
new ElasticsearchException(new IOException("boum")), randomBoolean(), randomBoolean(),
104104
randomNonNegativeLong(), randomNonNegativeLong());
105105

@@ -120,7 +120,6 @@ static SearchResponse randomSearchResponse() {
120120

121121
static void assertEqualResponses(AsyncSearchResponse expected, AsyncSearchResponse actual) {
122122
assertEquals(expected.getId(), actual.getId());
123-
assertEquals(expected.getVersion(), actual.getVersion());
124123
assertEquals(expected.status(), actual.status());
125124
assertEquals(expected.getFailure() == null, actual.getFailure() == null);
126125
assertEquals(expected.isRunning(), actual.isRunning());

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/search/action/AsyncSearchResponse.java

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
public class AsyncSearchResponse extends ActionResponse implements StatusToXContentObject {
2626
@Nullable
2727
private final String id;
28-
private final int version;
2928
@Nullable
3029
private final SearchResponse searchResponse;
3130
@Nullable
@@ -40,19 +39,17 @@ public class AsyncSearchResponse extends ActionResponse implements StatusToXCont
4039
* Creates an {@link AsyncSearchResponse} with meta-information only (not-modified).
4140
*/
4241
public AsyncSearchResponse(String id,
43-
int version,
4442
boolean isPartial,
4543
boolean isRunning,
4644
long startTimeMillis,
4745
long expirationTimeMillis) {
48-
this(id, version, null, null, isPartial, isRunning, startTimeMillis, expirationTimeMillis);
46+
this(id, null, null, isPartial, isRunning, startTimeMillis, expirationTimeMillis);
4947
}
5048

5149
/**
5250
* Creates a new {@link AsyncSearchResponse}
5351
*
5452
* @param id The id of the search for further retrieval, <code>null</code> if not stored.
55-
* @param version The version number of this response.
5653
* @param searchResponse The actual search response.
5754
* @param error The error if the search failed, <code>null</code> if the search is running
5855
* or has completed without failure.
@@ -61,15 +58,13 @@ public AsyncSearchResponse(String id,
6158
* @param startTimeMillis The start date of the search in milliseconds since epoch.
6259
*/
6360
public AsyncSearchResponse(String id,
64-
int version,
6561
SearchResponse searchResponse,
6662
ElasticsearchException error,
6763
boolean isPartial,
6864
boolean isRunning,
6965
long startTimeMillis,
7066
long expirationTimeMillis) {
7167
this.id = id;
72-
this.version = version;
7368
this.error = error;
7469
this.searchResponse = searchResponse;
7570
this.isPartial = isPartial;
@@ -80,7 +75,6 @@ public AsyncSearchResponse(String id,
8075

8176
public AsyncSearchResponse(StreamInput in) throws IOException {
8277
this.id = in.readOptionalString();
83-
this.version = in.readVInt();
8478
this.error = in.readOptionalWriteable(ElasticsearchException::new);
8579
this.searchResponse = in.readOptionalWriteable(SearchResponse::new);
8680
this.isPartial = in.readBoolean();
@@ -92,7 +86,6 @@ public AsyncSearchResponse(StreamInput in) throws IOException {
9286
@Override
9387
public void writeTo(StreamOutput out) throws IOException {
9488
out.writeOptionalString(id);
95-
out.writeVInt(version);
9689
out.writeOptionalWriteable(error);
9790
out.writeOptionalWriteable(searchResponse);
9891
out.writeBoolean(isPartial);
@@ -102,7 +95,7 @@ public void writeTo(StreamOutput out) throws IOException {
10295
}
10396

10497
public AsyncSearchResponse clone(String id) {
105-
return new AsyncSearchResponse(id, version, searchResponse, error, isPartial, false, startTimeMillis, expirationTimeMillis);
98+
return new AsyncSearchResponse(id, searchResponse, error, isPartial, false, startTimeMillis, expirationTimeMillis);
10699
}
107100

108101
/**
@@ -113,13 +106,6 @@ public String getId() {
113106
return id;
114107
}
115108

116-
/**
117-
* Returns the version of this response.
118-
*/
119-
public int getVersion() {
120-
return version;
121-
}
122-
123109
/**
124110
* Returns the current {@link SearchResponse} or <code>null</code> if not available.
125111
*
@@ -189,7 +175,6 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
189175
if (id != null) {
190176
builder.field("id", id);
191177
}
192-
builder.field("version", version);
193178
builder.field("is_partial", isPartial);
194179
builder.field("is_running", isRunning);
195180
builder.field("start_time_in_millis", startTimeMillis);

0 commit comments

Comments
 (0)