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
This commit is contained in:
parent
5ea89a4e7b
commit
563a78829f
|
@ -5,8 +5,7 @@ The update API allows to update a document based on a script provided.
|
||||||
The operation gets the document (collocated with the shard) from the
|
The operation gets the document (collocated with the shard) from the
|
||||||
index, runs the script (with optional script language and parameters),
|
index, runs the script (with optional script language and parameters),
|
||||||
and indexes back the result (also allows to delete, or ignore the
|
and indexes back the result (also allows to delete, or ignore the
|
||||||
operation). It uses versioning to make sure no updates have happened
|
operation).
|
||||||
during the "get" and "reindex".
|
|
||||||
|
|
||||||
Note, this operation still means full reindex of the document, it just
|
Note, this operation still means full reindex of the document, it just
|
||||||
removes some network roundtrips and reduces chances of version conflicts
|
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
|
||||||
By default the updated source is not returned.
|
By default the updated source is not returned.
|
||||||
See <<search-request-source-filtering, Source filtering>> for details.
|
See <<search-request-source-filtering, Source filtering>> for details.
|
||||||
|
|
||||||
|
|
||||||
`version`::
|
|
||||||
|
|
||||||
The update API uses the Elasticsearch versioning support internally to make
|
|
||||||
sure the document doesn't change during the update. You can use the `version`
|
|
||||||
parameter to specify that the document should only be updated if its version
|
|
||||||
matches the one specified.
|
|
||||||
|
|
||||||
[NOTE]
|
|
||||||
.The update API does not support versioning other than internal
|
|
||||||
=====================================================
|
|
||||||
|
|
||||||
External (version types `external` and `external_gte`) or forced (version type `force`)
|
|
||||||
versioning is not supported by the update API as it would result in Elasticsearch
|
|
||||||
version numbers being out of sync with the external system. Use the
|
|
||||||
<<docs-index_,`index` API>> instead.
|
|
||||||
|
|
||||||
=====================================================
|
|
||||||
|
|
||||||
`if_seq_no` and `if_primary_term`::
|
`if_seq_no` and `if_primary_term`::
|
||||||
|
|
||||||
Update operations can be made conditional and only be performed if the last
|
Update operations can be made conditional and only be performed if the last
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.elasticsearch.rest.action.document;
|
package org.elasticsearch.rest.action.document;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
import org.elasticsearch.action.index.IndexRequest;
|
import org.elasticsearch.action.index.IndexRequest;
|
||||||
import org.elasticsearch.action.support.ActiveShardCount;
|
import org.elasticsearch.action.support.ActiveShardCount;
|
||||||
import org.elasticsearch.action.update.UpdateRequest;
|
import org.elasticsearch.action.update.UpdateRequest;
|
||||||
|
@ -83,6 +84,12 @@ public class RestUpdateAction extends BaseRestHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRequest.retryOnConflict(request.paramAsInt("retry_on_conflict", updateRequest.retryOnConflict()));
|
updateRequest.retryOnConflict(request.paramAsInt("retry_on_conflict", updateRequest.retryOnConflict()));
|
||||||
|
if (request.hasParam("version") || request.hasParam("version_type")) {
|
||||||
|
final ActionRequestValidationException versioningError = new ActionRequestValidationException();
|
||||||
|
versioningError.addValidationError("internal versioning can not be used for optimistic concurrency control. " +
|
||||||
|
"Please use `if_seq_no` and `if_primary_term` instead");
|
||||||
|
throw versioningError;
|
||||||
|
}
|
||||||
|
|
||||||
updateRequest.setIfSeqNo(request.paramAsLong("if_seq_no", updateRequest.ifSeqNo()));
|
updateRequest.setIfSeqNo(request.paramAsLong("if_seq_no", updateRequest.ifSeqNo()));
|
||||||
updateRequest.setIfPrimaryTerm(request.paramAsLong("if_primary_term", updateRequest.ifPrimaryTerm()));
|
updateRequest.setIfPrimaryTerm(request.paramAsLong("if_primary_term", updateRequest.ifPrimaryTerm()));
|
||||||
|
|
|
@ -19,18 +19,31 @@
|
||||||
|
|
||||||
package org.elasticsearch.rest.action.document;
|
package org.elasticsearch.rest.action.document;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
|
import org.elasticsearch.common.bytes.BytesArray;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
|
import org.elasticsearch.index.VersionType;
|
||||||
import org.elasticsearch.rest.RestRequest;
|
import org.elasticsearch.rest.RestRequest;
|
||||||
import org.elasticsearch.rest.RestRequest.Method;
|
import org.elasticsearch.rest.RestRequest.Method;
|
||||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||||
import org.elasticsearch.test.rest.RestActionTestCase;
|
import org.elasticsearch.test.rest.RestActionTestCase;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class RestUpdateActionTests extends RestActionTestCase {
|
public class RestUpdateActionTests extends RestActionTestCase {
|
||||||
|
|
||||||
|
private RestUpdateAction action;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUpAction() {
|
public void setUpAction() {
|
||||||
new RestUpdateAction(Settings.EMPTY, controller());
|
action = new RestUpdateAction(Settings.EMPTY, controller());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTypeInPath() {
|
public void testTypeInPath() {
|
||||||
|
@ -47,4 +60,32 @@ public class RestUpdateActionTests extends RestActionTestCase {
|
||||||
.build();
|
.build();
|
||||||
dispatchRequest(validRequest);
|
dispatchRequest(validRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testUpdateDocVersion() {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
if (randomBoolean()) {
|
||||||
|
params.put("version", Long.toString(randomNonNegativeLong()));
|
||||||
|
params.put("version_type", randomFrom(VersionType.values()).name());
|
||||||
|
} else if (randomBoolean()) {
|
||||||
|
params.put("version", Long.toString(randomNonNegativeLong()));
|
||||||
|
} else {
|
||||||
|
params.put("version_type", randomFrom(VersionType.values()).name());
|
||||||
|
}
|
||||||
|
String content =
|
||||||
|
"{\n" +
|
||||||
|
" \"doc\" : {\n" +
|
||||||
|
" \"name\" : \"new_name\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}";
|
||||||
|
FakeRestRequest updateRequest = new FakeRestRequest.Builder(xContentRegistry())
|
||||||
|
.withMethod(RestRequest.Method.POST)
|
||||||
|
.withPath("test/_update/1")
|
||||||
|
.withParams(params)
|
||||||
|
.withContent(new BytesArray(content), XContentType.JSON)
|
||||||
|
.build();
|
||||||
|
ActionRequestValidationException e = expectThrows(ActionRequestValidationException.class,
|
||||||
|
() -> action.prepareRequest(updateRequest, mock(NodeClient.class)));
|
||||||
|
assertThat(e.getMessage(), containsString("internal versioning can not be used for optimistic concurrency control. " +
|
||||||
|
"Please use `if_seq_no` and `if_primary_term` instead"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue