Skip to content

Commit afa9b35

Browse files
PnPiednhatn
authored andcommitted
Do not allow version in Rest Update API (#43516)
The versioning of Update API doesn't rely on version number anymore (and rather on sequence number). But in rest api level we ignored the "version" and "version_type" parameter, so that the server cannot raise the exception when whey were set. This PR restores "version" and "version_type" parsing in Update Rest API so that we can get the appropriate errors. Relates to #42497
1 parent 60eb7f7 commit afa9b35

File tree

3 files changed

+50
-22
lines changed

3 files changed

+50
-22
lines changed

docs/reference/docs/update.asciidoc

+1-21
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ The update API allows to update a document based on a script provided.
55
The operation gets the document (collocated with the shard) from the
66
index, runs the script (with optional script language and parameters),
77
and indexes back the result (also allows to delete, or ignore the
8-
operation). It uses versioning to make sure no updates have happened
9-
during the "get" and "reindex".
8+
operation).
109

1110
Note, this operation still means full reindex of the document, it just
1211
removes some network roundtrips and reduces chances of version conflicts
@@ -333,25 +332,6 @@ Allows to control if and how the updated source should be returned in the respon
333332
By default the updated source is not returned.
334333
See <<search-request-source-filtering, Source filtering>> for details.
335334

336-
337-
`version`::
338-
339-
The update API uses the Elasticsearch versioning support internally to make
340-
sure the document doesn't change during the update. You can use the `version`
341-
parameter to specify that the document should only be updated if its version
342-
matches the one specified.
343-
344-
[NOTE]
345-
.The update API does not support versioning other than internal
346-
=====================================================
347-
348-
External (version types `external` and `external_gte`) or forced (version type `force`)
349-
versioning is not supported by the update API as it would result in Elasticsearch
350-
version numbers being out of sync with the external system. Use the
351-
<<docs-index_,`index` API>> instead.
352-
353-
=====================================================
354-
355335
`if_seq_no` and `if_primary_term`::
356336

357337
Update operations can be made conditional and only be performed if the last

server/src/main/java/org/elasticsearch/rest/action/document/RestUpdateAction.java

+7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.rest.action.document;
2121

2222
import org.apache.logging.log4j.LogManager;
23+
import org.elasticsearch.action.ActionRequestValidationException;
2324
import org.elasticsearch.action.index.IndexRequest;
2425
import org.elasticsearch.action.support.ActiveShardCount;
2526
import org.elasticsearch.action.update.UpdateRequest;
@@ -83,6 +84,12 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
8384
}
8485

8586
updateRequest.retryOnConflict(request.paramAsInt("retry_on_conflict", updateRequest.retryOnConflict()));
87+
if (request.hasParam("version") || request.hasParam("version_type")) {
88+
final ActionRequestValidationException versioningError = new ActionRequestValidationException();
89+
versioningError.addValidationError("internal versioning can not be used for optimistic concurrency control. " +
90+
"Please use `if_seq_no` and `if_primary_term` instead");
91+
throw versioningError;
92+
}
8693

8794
updateRequest.setIfSeqNo(request.paramAsLong("if_seq_no", updateRequest.ifSeqNo()));
8895
updateRequest.setIfPrimaryTerm(request.paramAsLong("if_primary_term", updateRequest.ifPrimaryTerm()));

server/src/test/java/org/elasticsearch/rest/action/document/RestUpdateActionTests.java

+42-1
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,31 @@
1919

2020
package org.elasticsearch.rest.action.document;
2121

22+
import org.elasticsearch.action.ActionRequestValidationException;
23+
import org.elasticsearch.client.node.NodeClient;
24+
import org.elasticsearch.common.bytes.BytesArray;
2225
import org.elasticsearch.common.settings.Settings;
26+
import org.elasticsearch.common.xcontent.XContentType;
27+
import org.elasticsearch.index.VersionType;
2328
import org.elasticsearch.rest.RestRequest;
2429
import org.elasticsearch.rest.RestRequest.Method;
2530
import org.elasticsearch.test.rest.FakeRestRequest;
2631
import org.elasticsearch.test.rest.RestActionTestCase;
2732
import org.junit.Before;
2833

34+
import java.util.HashMap;
35+
import java.util.Map;
36+
37+
import static org.hamcrest.CoreMatchers.containsString;
38+
import static org.mockito.Mockito.mock;
39+
2940
public class RestUpdateActionTests extends RestActionTestCase {
3041

42+
private RestUpdateAction action;
43+
3144
@Before
3245
public void setUpAction() {
33-
new RestUpdateAction(Settings.EMPTY, controller());
46+
action = new RestUpdateAction(Settings.EMPTY, controller());
3447
}
3548

3649
public void testTypeInPath() {
@@ -47,4 +60,32 @@ public void testTypeInPath() {
4760
.build();
4861
dispatchRequest(validRequest);
4962
}
63+
64+
public void testUpdateDocVersion() {
65+
Map<String, String> params = new HashMap<>();
66+
if (randomBoolean()) {
67+
params.put("version", Long.toString(randomNonNegativeLong()));
68+
params.put("version_type", randomFrom(VersionType.values()).name());
69+
} else if (randomBoolean()) {
70+
params.put("version", Long.toString(randomNonNegativeLong()));
71+
} else {
72+
params.put("version_type", randomFrom(VersionType.values()).name());
73+
}
74+
String content =
75+
"{\n" +
76+
" \"doc\" : {\n" +
77+
" \"name\" : \"new_name\"\n" +
78+
" }\n" +
79+
"}";
80+
FakeRestRequest updateRequest = new FakeRestRequest.Builder(xContentRegistry())
81+
.withMethod(RestRequest.Method.POST)
82+
.withPath("test/_update/1")
83+
.withParams(params)
84+
.withContent(new BytesArray(content), XContentType.JSON)
85+
.build();
86+
ActionRequestValidationException e = expectThrows(ActionRequestValidationException.class,
87+
() -> action.prepareRequest(updateRequest, mock(NodeClient.class)));
88+
assertThat(e.getMessage(), containsString("internal versioning can not be used for optimistic concurrency control. " +
89+
"Please use `if_seq_no` and `if_primary_term` instead"));
90+
}
5091
}

0 commit comments

Comments
 (0)