Fix HLRC parsing of CancelTasks response (#47017)
Adds support for proper cancel tasks parsing. Closes #45414
This commit is contained in:
parent
2ec047db04
commit
c9eba17517
|
@ -53,6 +53,7 @@ import org.elasticsearch.client.core.MultiTermVectorsRequest;
|
|||
import org.elasticsearch.client.core.TermVectorsRequest;
|
||||
import org.elasticsearch.client.indices.AnalyzeRequest;
|
||||
import org.elasticsearch.client.security.RefreshPolicy;
|
||||
import org.elasticsearch.client.tasks.TaskId;
|
||||
import org.elasticsearch.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Priority;
|
||||
|
@ -81,13 +82,13 @@ import org.elasticsearch.rest.action.search.RestSearchAction;
|
|||
import org.elasticsearch.script.mustache.MultiSearchTemplateRequest;
|
||||
import org.elasticsearch.script.mustache.SearchTemplateRequest;
|
||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||
import org.elasticsearch.tasks.TaskId;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -1041,19 +1042,41 @@ final class RequestConverters {
|
|||
}
|
||||
|
||||
Params withNodes(String[] nodes) {
|
||||
if (nodes != null && nodes.length > 0) {
|
||||
return withNodes(Arrays.asList(nodes));
|
||||
}
|
||||
|
||||
Params withNodes(List<String> nodes) {
|
||||
if (nodes != null && nodes.size() > 0) {
|
||||
return putParam("nodes", String.join(",", nodes));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Params withActions(String[] actions) {
|
||||
if (actions != null && actions.length > 0) {
|
||||
return withActions(Arrays.asList(actions));
|
||||
}
|
||||
|
||||
Params withActions(List<String> actions) {
|
||||
if (actions != null && actions.size() > 0) {
|
||||
return putParam("actions", String.join(",", actions));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Params withTaskId(org.elasticsearch.tasks.TaskId taskId) {
|
||||
if (taskId != null && taskId.isSet()) {
|
||||
return putParam("task_id", taskId.toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Params withParentTaskId(org.elasticsearch.tasks.TaskId parentTaskId) {
|
||||
if (parentTaskId != null && parentTaskId.isSet()) {
|
||||
return putParam("parent_task_id", parentTaskId.toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Params withTaskId(TaskId taskId) {
|
||||
if (taskId != null && taskId.isSet()) {
|
||||
return putParam("task_id", taskId.toString());
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
package org.elasticsearch.client;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksResponse;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
|
||||
import org.elasticsearch.client.tasks.CancelTasksRequest;
|
||||
import org.elasticsearch.client.tasks.CancelTasksResponse;
|
||||
import org.elasticsearch.client.tasks.GetTaskRequest;
|
||||
import org.elasticsearch.client.tasks.GetTaskResponse;
|
||||
|
||||
|
|
|
@ -21,23 +21,24 @@ package org.elasticsearch.client;
|
|||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
|
||||
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
|
||||
import org.elasticsearch.client.tasks.CancelTasksRequest;
|
||||
import org.elasticsearch.client.tasks.GetTaskRequest;
|
||||
|
||||
final class TasksRequestConverters {
|
||||
|
||||
private TasksRequestConverters() {}
|
||||
|
||||
static Request cancelTasks(CancelTasksRequest cancelTasksRequest) {
|
||||
static Request cancelTasks(CancelTasksRequest req) {
|
||||
Request request = new Request(HttpPost.METHOD_NAME, "/_tasks/_cancel");
|
||||
RequestConverters.Params params = new RequestConverters.Params();
|
||||
params.withTimeout(cancelTasksRequest.getTimeout())
|
||||
.withTaskId(cancelTasksRequest.getTaskId())
|
||||
.withNodes(cancelTasksRequest.getNodes())
|
||||
.withParentTaskId(cancelTasksRequest.getParentTaskId())
|
||||
.withActions(cancelTasksRequest.getActions());
|
||||
req.getTimeout().ifPresent(params::withTimeout);
|
||||
req.getTaskId().ifPresent(params::withTaskId);
|
||||
req.getParentTaskId().ifPresent(params::withParentTaskId);
|
||||
params
|
||||
.withNodes(req.getNodes())
|
||||
.withActions(req.getActions());
|
||||
request.addParameters(params.asMap());
|
||||
return request;
|
||||
}
|
||||
|
@ -70,5 +71,5 @@ final class TasksRequestConverters {
|
|||
request.addParameters(params.asMap());
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import org.elasticsearch.client.Validatable;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CancelTasksRequest implements Validatable {
|
||||
|
||||
private final List<String> nodes = new ArrayList<>();
|
||||
private final List<String> actions = new ArrayList<>();
|
||||
private Optional<TimeValue> timeout = Optional.empty();
|
||||
private Optional<TaskId> parentTaskId = Optional.empty();
|
||||
private Optional<TaskId> taskId = Optional.empty();
|
||||
|
||||
CancelTasksRequest(){}
|
||||
|
||||
void setNodes(List<String> nodes) {
|
||||
this.nodes.addAll(nodes);
|
||||
}
|
||||
|
||||
public List<String> getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
void setTimeout(TimeValue timeout) {
|
||||
this.timeout = Optional.of(timeout);
|
||||
}
|
||||
|
||||
public Optional<TimeValue> getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
void setActions(List<String> actions) {
|
||||
this.actions.addAll(actions);
|
||||
}
|
||||
|
||||
public List<String> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
void setParentTaskId(TaskId parentTaskId) {
|
||||
this.parentTaskId = Optional.of(parentTaskId);
|
||||
}
|
||||
|
||||
public Optional<TaskId> getParentTaskId() {
|
||||
return parentTaskId;
|
||||
}
|
||||
|
||||
void setTaskId(TaskId taskId) {
|
||||
this.taskId = Optional.of(taskId);
|
||||
}
|
||||
|
||||
public Optional<TaskId> getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof CancelTasksRequest)) return false;
|
||||
CancelTasksRequest that = (CancelTasksRequest) o;
|
||||
return Objects.equals(getNodes(), that.getNodes()) &&
|
||||
Objects.equals(getActions(), that.getActions()) &&
|
||||
Objects.equals(getTimeout(), that.getTimeout()) &&
|
||||
Objects.equals(getParentTaskId(), that.getParentTaskId()) &&
|
||||
Objects.equals(getTaskId(), that.getTaskId()) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getNodes(), getActions(), getTimeout(), getParentTaskId(), getTaskId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CancelTasksRequest{" +
|
||||
"nodes=" + nodes +
|
||||
", actions=" + actions +
|
||||
", timeout=" + timeout +
|
||||
", parentTaskId=" + parentTaskId +
|
||||
", taskId=" + taskId +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Optional<TimeValue> timeout = Optional.empty();
|
||||
private Optional<TaskId> taskId = Optional.empty();
|
||||
private Optional<TaskId> parentTaskId = Optional.empty();
|
||||
private List<String> actionsFilter = new ArrayList<>();
|
||||
private List<String> nodesFilter = new ArrayList<>();
|
||||
|
||||
public Builder withTimeout(TimeValue timeout){
|
||||
this.timeout = Optional.of(timeout);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withTaskId(TaskId taskId){
|
||||
this.taskId = Optional.of(taskId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withParentTaskId(TaskId taskId){
|
||||
this.parentTaskId = Optional.of(taskId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withActionsFiltered(List<String> actions){
|
||||
this.actionsFilter.clear();
|
||||
this.actionsFilter.addAll(actions);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withNodesFiltered(List<String> nodes){
|
||||
this.nodesFilter.clear();
|
||||
this.nodesFilter.addAll(nodes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CancelTasksRequest build() {
|
||||
CancelTasksRequest request = new CancelTasksRequest();
|
||||
timeout.ifPresent(request::setTimeout);
|
||||
taskId.ifPresent(request::setTaskId);
|
||||
parentTaskId.ifPresent(request::setParentTaskId);
|
||||
request.setNodes(nodesFilter);
|
||||
request.setActions(actionsFilter);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
|
||||
|
||||
/**
|
||||
* cancel tasks response that contains
|
||||
* - task failures
|
||||
* - node failures
|
||||
* - tasks
|
||||
*/
|
||||
public class CancelTasksResponse extends ListTasksResponse {
|
||||
|
||||
CancelTasksResponse(List<NodeData> nodesInfoData,
|
||||
List<TaskOperationFailure> taskFailures,
|
||||
List<ElasticsearchException> nodeFailures) {
|
||||
super(nodesInfoData, taskFailures, nodeFailures);
|
||||
}
|
||||
|
||||
public static CancelTasksResponse fromXContent(final XContentParser parser) throws IOException {
|
||||
return PARSER.parse(parser, null);
|
||||
}
|
||||
|
||||
private static ConstructingObjectParser<CancelTasksResponse, Void> PARSER;
|
||||
|
||||
static {
|
||||
ConstructingObjectParser<CancelTasksResponse, Void> parser = new ConstructingObjectParser<>("cancel_tasks_response", true,
|
||||
constructingObjects -> {
|
||||
int i = 0;
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TaskOperationFailure> tasksFailures = (List<TaskOperationFailure>) constructingObjects[i++];
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ElasticsearchException> nodeFailures = (List<ElasticsearchException>) constructingObjects[i++];
|
||||
@SuppressWarnings("unchecked")
|
||||
List<NodeData> nodesInfoData = (List<NodeData>) constructingObjects[i];
|
||||
return new CancelTasksResponse(nodesInfoData, tasksFailures, nodeFailures);
|
||||
});
|
||||
|
||||
parser.declareObjectArray(optionalConstructorArg(), (p, c) ->
|
||||
TaskOperationFailure.fromXContent(p), new ParseField("task_failures"));
|
||||
parser.declareObjectArray(optionalConstructorArg(), (p, c) ->
|
||||
ElasticsearchException.fromXContent(p), new ParseField("node_failures"));
|
||||
parser.declareNamedObjects(optionalConstructorArg(), NodeData.PARSER, new ParseField("nodes"));
|
||||
PARSER = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CancelTasksResponse{" +
|
||||
"taskFailures=" + taskFailures +
|
||||
", nodeFailures=" + nodeFailures +
|
||||
", nodesInfoData=" + nodesInfoData +
|
||||
", tasks=" + tasks +
|
||||
", taskGroups=" + taskGroups +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
|
||||
/**
|
||||
* client side counterpart of server side
|
||||
* {@link org.elasticsearch.ElasticsearchException}
|
||||
* It wraps the same content but it is not throwable.
|
||||
*/
|
||||
public class ElasticsearchException {
|
||||
|
||||
private static final String TYPE = "type";
|
||||
private static final String REASON = "reason";
|
||||
private static final String CAUSED_BY = "caused_by";
|
||||
private static final ParseField SUPPRESSED = new ParseField("suppressed");
|
||||
private static final String STACK_TRACE = "stack_trace";
|
||||
private static final String HEADER = "header";
|
||||
private static final String ROOT_CAUSE = "root_cause";
|
||||
|
||||
private String msg;
|
||||
private ElasticsearchException cause;
|
||||
private final Map<String, List<String>> headers = new HashMap<>();
|
||||
private final List<ElasticsearchException> suppressed = new ArrayList<>();
|
||||
|
||||
ElasticsearchException(String msg) {
|
||||
this.msg = msg;
|
||||
this.cause = null;
|
||||
}
|
||||
|
||||
ElasticsearchException(String msg, ElasticsearchException cause) {
|
||||
this.msg = msg;
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public ElasticsearchException getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
public List<ElasticsearchException> getSuppressed() {
|
||||
return suppressed;
|
||||
}
|
||||
|
||||
void addSuppressed(List<ElasticsearchException> suppressed){
|
||||
this.suppressed.addAll(suppressed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a {@link ElasticsearchException} from a {@link XContentParser}. This does not
|
||||
* return the original exception type (ie NodeClosedException for example) but just wraps
|
||||
* the type, the reason and the cause of the exception. It also recursively parses the
|
||||
* tree structure of the cause, returning it as a tree structure of {@link ElasticsearchException}
|
||||
* instances.
|
||||
*/
|
||||
static ElasticsearchException fromXContent(XContentParser parser) throws IOException {
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);
|
||||
return innerFromXContent(parser, false);
|
||||
}
|
||||
|
||||
private static ElasticsearchException innerFromXContent(XContentParser parser, boolean parseRootCauses) throws IOException {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);
|
||||
|
||||
String type = null, reason = null, stack = null;
|
||||
ElasticsearchException cause = null;
|
||||
Map<String, List<String>> headers = new HashMap<>();
|
||||
List<ElasticsearchException> rootCauses = new ArrayList<>();
|
||||
List<ElasticsearchException> suppressed = new ArrayList<>();
|
||||
|
||||
for (; token == XContentParser.Token.FIELD_NAME; token = parser.nextToken()) {
|
||||
String currentFieldName = parser.currentName();
|
||||
token = parser.nextToken();
|
||||
|
||||
if (token.isValue()) {
|
||||
if (TYPE.equals(currentFieldName)) {
|
||||
type = parser.text();
|
||||
} else if (REASON.equals(currentFieldName)) {
|
||||
reason = parser.text();
|
||||
} else if (STACK_TRACE.equals(currentFieldName)) {
|
||||
stack = parser.text();
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (CAUSED_BY.equals(currentFieldName)) {
|
||||
cause = fromXContent(parser);
|
||||
} else if (HEADER.equals(currentFieldName)) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else {
|
||||
List<String> values = headers.getOrDefault(currentFieldName, new ArrayList<>());
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
values.add(parser.text());
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
values.add(parser.text());
|
||||
} else {
|
||||
parser.skipChildren();
|
||||
}
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
parser.skipChildren();
|
||||
}
|
||||
headers.put(currentFieldName, values);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Any additional metadata object added by the metadataToXContent method is ignored
|
||||
// and skipped, so that the parser does not fail on unknown fields. The parser only
|
||||
// support metadata key-pairs and metadata arrays of values.
|
||||
parser.skipChildren();
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if (parseRootCauses && ROOT_CAUSE.equals(currentFieldName)) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
rootCauses.add(fromXContent(parser));
|
||||
}
|
||||
} else if (SUPPRESSED.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
suppressed.add(fromXContent(parser));
|
||||
}
|
||||
} else {
|
||||
// Parse the array and add each item to the corresponding list of metadata.
|
||||
// Arrays of objects are not supported yet and just ignored and skipped.
|
||||
List<String> values = new ArrayList<>();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
values.add(parser.text());
|
||||
} else {
|
||||
parser.skipChildren();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElasticsearchException e = new ElasticsearchException(buildMessage(type, reason, stack), cause);
|
||||
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
|
||||
e.addHeader(header.getKey(), header.getValue());
|
||||
}
|
||||
|
||||
// Adds root causes as suppressed exception. This way they are not lost
|
||||
// after parsing and can be retrieved using getSuppressed() method.
|
||||
e.suppressed.addAll(rootCauses);
|
||||
e.suppressed.addAll(suppressed);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void addHeader(String key, List<String> value) {
|
||||
headers.put(key,value);
|
||||
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
static String buildMessage(String type, String reason, String stack) {
|
||||
StringBuilder message = new StringBuilder("Elasticsearch exception [");
|
||||
message.append(TYPE).append('=').append(type).append(", ");
|
||||
message.append(REASON).append('=').append(reason);
|
||||
if (stack != null) {
|
||||
message.append(", ").append(STACK_TRACE).append('=').append(stack);
|
||||
}
|
||||
message.append(']');
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ElasticsearchException)) return false;
|
||||
ElasticsearchException that = (ElasticsearchException) o;
|
||||
return Objects.equals(getMsg(), that.getMsg()) &&
|
||||
Objects.equals(getCause(), that.getCause()) &&
|
||||
Objects.equals(getHeaders(), that.getHeaders()) &&
|
||||
Objects.equals(getSuppressed(), that.getSuppressed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getMsg(), getCause(), getHeaders(), getSuppressed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ElasticsearchException{" +
|
||||
"msg='" + msg + '\'' +
|
||||
", cause=" + cause +
|
||||
", headers=" + headers +
|
||||
", suppressed=" + suppressed +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -101,8 +101,8 @@ public class GetTaskRequest implements Validatable {
|
|||
}
|
||||
GetTaskRequest other = (GetTaskRequest) obj;
|
||||
return Objects.equals(nodeId, other.nodeId) &&
|
||||
taskId == other.taskId &&
|
||||
waitForCompletion == other.waitForCompletion &&
|
||||
taskId == other.taskId &&
|
||||
waitForCompletion == other.waitForCompletion &&
|
||||
Objects.equals(timeout, other.timeout);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.client.tasks;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
|
@ -31,16 +30,16 @@ public class GetTaskResponse {
|
|||
private final TaskInfo taskInfo;
|
||||
public static final ParseField COMPLETED = new ParseField("completed");
|
||||
public static final ParseField TASK = new ParseField("task");
|
||||
|
||||
|
||||
public GetTaskResponse(boolean completed, TaskInfo taskInfo) {
|
||||
this.completed = completed;
|
||||
this.taskInfo = taskInfo;
|
||||
}
|
||||
|
||||
|
||||
public boolean isCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
|
||||
public TaskInfo getTaskInfo() {
|
||||
return taskInfo;
|
||||
}
|
||||
|
@ -50,9 +49,9 @@ public class GetTaskResponse {
|
|||
static {
|
||||
PARSER.declareBoolean(constructorArg(), COMPLETED);
|
||||
PARSER.declareObject(constructorArg(), (p, c) -> TaskInfo.fromXContent(p), TASK);
|
||||
}
|
||||
}
|
||||
|
||||
public static GetTaskResponse fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class ListTasksResponse {
|
||||
|
||||
protected final List<TaskOperationFailure> taskFailures = new ArrayList<>();
|
||||
protected final List<ElasticsearchException> nodeFailures = new ArrayList<>();
|
||||
protected final List<NodeData> nodesInfoData = new ArrayList<>();
|
||||
protected final List<TaskInfo> tasks = new ArrayList<>();
|
||||
protected final List<TaskGroup> taskGroups = new ArrayList<>();
|
||||
|
||||
ListTasksResponse(List<NodeData> nodesInfoData,
|
||||
List<TaskOperationFailure> taskFailures,
|
||||
List<ElasticsearchException> nodeFailures) {
|
||||
if (taskFailures != null) {
|
||||
this.taskFailures.addAll(taskFailures);
|
||||
}
|
||||
if (nodeFailures != null) {
|
||||
this.nodeFailures.addAll(nodeFailures);
|
||||
}
|
||||
if (nodesInfoData != null) {
|
||||
this.nodesInfoData.addAll(nodesInfoData);
|
||||
}
|
||||
this.tasks.addAll(this
|
||||
.nodesInfoData
|
||||
.stream()
|
||||
.flatMap(nodeData -> nodeData.getTasks().stream())
|
||||
.collect(toList())
|
||||
);
|
||||
this.taskGroups.addAll(buildTaskGroups());
|
||||
}
|
||||
|
||||
private List<TaskGroup> buildTaskGroups() {
|
||||
Map<TaskId, TaskGroup.Builder> taskGroups = new HashMap<>();
|
||||
List<TaskGroup.Builder> topLevelTasks = new ArrayList<>();
|
||||
// First populate all tasks
|
||||
for (TaskInfo taskInfo : this.tasks) {
|
||||
taskGroups.put(taskInfo.getTaskId(), TaskGroup.builder(taskInfo));
|
||||
}
|
||||
|
||||
// Now go through all task group builders and add children to their parents
|
||||
for (TaskGroup.Builder taskGroup : taskGroups.values()) {
|
||||
TaskId parentTaskId = taskGroup.getTaskInfo().getParentTaskId();
|
||||
if (parentTaskId != null) {
|
||||
TaskGroup.Builder parentTask = taskGroups.get(parentTaskId);
|
||||
if (parentTask != null) {
|
||||
// we found parent in the list of tasks - add it to the parent list
|
||||
parentTask.addGroup(taskGroup);
|
||||
} else {
|
||||
// we got zombie or the parent was filtered out - add it to the top task list
|
||||
topLevelTasks.add(taskGroup);
|
||||
}
|
||||
} else {
|
||||
// top level task - add it to the top task list
|
||||
topLevelTasks.add(taskGroup);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(topLevelTasks.stream().map(TaskGroup.Builder::build).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public List<TaskInfo> getTasks() {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public Map<String, List<TaskInfo>> getPerNodeTasks() {
|
||||
return getTasks()
|
||||
.stream()
|
||||
.collect(groupingBy(TaskInfo::getNodeId));
|
||||
}
|
||||
|
||||
public List<TaskOperationFailure> getTaskFailures() {
|
||||
return taskFailures;
|
||||
}
|
||||
|
||||
public List<ElasticsearchException> getNodeFailures() {
|
||||
return nodeFailures;
|
||||
}
|
||||
|
||||
public List<TaskGroup> getTaskGroups() {
|
||||
return taskGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ListTasksResponse)) return false;
|
||||
ListTasksResponse response = (ListTasksResponse) o;
|
||||
return nodesInfoData.equals(response.nodesInfoData) &&
|
||||
Objects.equals
|
||||
(getTaskFailures(), response.getTaskFailures()) &&
|
||||
Objects.equals(getNodeFailures(), response.getNodeFailures()) &&
|
||||
Objects.equals(getTasks(), response.getTasks()) &&
|
||||
Objects.equals(getTaskGroups(), response.getTaskGroups());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(nodesInfoData, getTaskFailures(), getNodeFailures(), getTasks(), getTaskGroups());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CancelTasksResponse{" +
|
||||
"nodesInfoData=" + nodesInfoData +
|
||||
", taskFailures=" + taskFailures +
|
||||
", nodeFailures=" + nodeFailures +
|
||||
", tasks=" + tasks +
|
||||
", taskGroups=" + taskGroups +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
class NodeData {
|
||||
|
||||
private String nodeId;
|
||||
private String name;
|
||||
private String transportAddress;
|
||||
private String host;
|
||||
private String ip;
|
||||
private final List<String> roles = new ArrayList<>();
|
||||
private final Map<String,String> attributes = new HashMap<>();
|
||||
private final List<TaskInfo> tasks = new ArrayList<>();
|
||||
|
||||
NodeData(String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setAttributes(Map<String, String> attributes) {
|
||||
if(attributes!=null){
|
||||
this.attributes.putAll(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
void setTransportAddress(String transportAddress) {
|
||||
this.transportAddress = transportAddress;
|
||||
}
|
||||
|
||||
void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
void setRoles(List<String> roles) {
|
||||
if(roles!=null){
|
||||
this.roles.addAll(roles);
|
||||
}
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTransportAddress() {
|
||||
return transportAddress;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public Map<String, String> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public List<TaskInfo> getTasks() {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
void setTasks(List<TaskInfo> tasks) {
|
||||
if(tasks!=null){
|
||||
this.tasks.addAll(tasks);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NodeData{" +
|
||||
"nodeId='" + nodeId + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", transportAddress='" + transportAddress + '\'' +
|
||||
", host='" + host + '\'' +
|
||||
", ip='" + ip + '\'' +
|
||||
", roles=" + roles +
|
||||
", attributes=" + attributes +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof NodeData)) return false;
|
||||
NodeData nodeData = (NodeData) o;
|
||||
return Objects.equals(getNodeId(), nodeData.getNodeId()) &&
|
||||
Objects.equals(getName(), nodeData.getName()) &&
|
||||
Objects.equals(getTransportAddress(), nodeData.getTransportAddress()) &&
|
||||
Objects.equals(getHost(), nodeData.getHost()) &&
|
||||
Objects.equals(getIp(), nodeData.getIp()) &&
|
||||
Objects.equals(getRoles(), nodeData.getRoles()) &&
|
||||
Objects.equals(getAttributes(), nodeData.getAttributes()) &&
|
||||
Objects.equals(getTasks(), nodeData.getTasks());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getNodeId(), getName(), getTransportAddress(), getHost(), getIp(), getRoles(), getAttributes(), getTasks());
|
||||
}
|
||||
|
||||
public static final ObjectParser.NamedObjectParser<NodeData, Void> PARSER;
|
||||
|
||||
static {
|
||||
ObjectParser<NodeData, Void> parser = new ObjectParser<>("nodes");
|
||||
parser.declareString(NodeData::setName, new ParseField("name"));
|
||||
parser.declareString(NodeData::setTransportAddress, new ParseField("transport_address"));
|
||||
parser.declareString(NodeData::setHost, new ParseField("host"));
|
||||
parser.declareString(NodeData::setIp, new ParseField("ip"));
|
||||
parser.declareStringArray(NodeData::setRoles, new ParseField("roles"));
|
||||
parser.declareField(NodeData::setAttributes,
|
||||
(p, c) -> p.mapStrings(),
|
||||
new ParseField("attributes"),
|
||||
ObjectParser.ValueType.OBJECT);
|
||||
parser.declareNamedObjects(NodeData::setTasks, TaskInfo.PARSER, new ParseField("tasks"));
|
||||
PARSER = (XContentParser p, Void v, String nodeId) -> parser.parse(p, new NodeData(nodeId), null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Client side counterpart of server side version.
|
||||
*
|
||||
* {@link org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup}
|
||||
*/
|
||||
public class TaskGroup {
|
||||
|
||||
private final TaskInfo task;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TaskGroup{" +
|
||||
"task=" + task +
|
||||
", childTasks=" + childTasks +
|
||||
'}';
|
||||
}
|
||||
|
||||
private final List<TaskGroup> childTasks = new ArrayList<>();
|
||||
|
||||
public TaskGroup(TaskInfo task, List<TaskGroup> childTasks) {
|
||||
this.task = task;
|
||||
this.childTasks.addAll(childTasks);
|
||||
}
|
||||
|
||||
public static TaskGroup.Builder builder(TaskInfo taskInfo) {
|
||||
return new TaskGroup.Builder(taskInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TaskGroup)) return false;
|
||||
TaskGroup taskGroup = (TaskGroup) o;
|
||||
return Objects.equals(task, taskGroup.task) &&
|
||||
Objects.equals(getChildTasks(), taskGroup.getChildTasks());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(task, getChildTasks());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private TaskInfo taskInfo;
|
||||
private List<TaskGroup.Builder> childTasks;
|
||||
|
||||
private Builder(TaskInfo taskInfo) {
|
||||
this.taskInfo = taskInfo;
|
||||
childTasks = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addGroup(TaskGroup.Builder builder) {
|
||||
childTasks.add(builder);
|
||||
}
|
||||
|
||||
public TaskInfo getTaskInfo() {
|
||||
return taskInfo;
|
||||
}
|
||||
|
||||
public TaskGroup build() {
|
||||
return new TaskGroup(
|
||||
taskInfo,
|
||||
childTasks.stream().map(TaskGroup.Builder::build).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public TaskInfo getTaskInfo() {
|
||||
return task;
|
||||
}
|
||||
|
||||
public List<TaskGroup> getChildTasks() {
|
||||
return childTasks;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* client side version of a {@link org.elasticsearch.tasks.TaskId}
|
||||
*/
|
||||
public class TaskId {
|
||||
|
||||
protected final String nodeId;
|
||||
protected final long id;
|
||||
|
||||
public TaskId(String nodeId, long id) {
|
||||
this.nodeId = nodeId;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* accepts a raw format task id
|
||||
* @param taskId expected to be nodeid:taskId
|
||||
*/
|
||||
public TaskId(String taskId) {
|
||||
if (taskId == null) {
|
||||
throw new IllegalArgumentException("null task id");
|
||||
}
|
||||
String[] s = taskId.split(":");
|
||||
if (s.length != 2) {
|
||||
throw new IllegalArgumentException("malformed task id " + taskId);
|
||||
}
|
||||
this.nodeId = s[0];
|
||||
try {
|
||||
this.id = Long.parseLong(s[1]);
|
||||
} catch (NumberFormatException ex) {
|
||||
throw new IllegalArgumentException("malformed task id " + taskId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isSet() {
|
||||
return id != -1L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isSet()) {
|
||||
return nodeId + ":" + id;
|
||||
} else {
|
||||
return "unset";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TaskId)) return false;
|
||||
TaskId taskId = (TaskId) o;
|
||||
return getId() == taskId.getId() &&
|
||||
Objects.equals(getNodeId(), taskId.getNodeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getNodeId(), getId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* client side counterpart of server side
|
||||
* <p>
|
||||
* {@link org.elasticsearch.tasks.TaskInfo}
|
||||
*/
|
||||
public class TaskInfo {
|
||||
|
||||
private TaskId taskId;
|
||||
private String type;
|
||||
private String action;
|
||||
private String description;
|
||||
private long startTime;
|
||||
private long runningTimeNanos;
|
||||
private boolean cancellable;
|
||||
private TaskId parentTaskId;
|
||||
private final Map<String, Object> status = new HashMap<>();
|
||||
private final Map<String, String> headers = new HashMap<>();
|
||||
|
||||
public TaskInfo(TaskId taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public TaskId getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return taskId.nodeId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
void setAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
void setStartTime(long startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public long getRunningTimeNanos() {
|
||||
return runningTimeNanos;
|
||||
}
|
||||
|
||||
void setRunningTimeNanos(long runningTimeNanos) {
|
||||
this.runningTimeNanos = runningTimeNanos;
|
||||
}
|
||||
|
||||
public boolean isCancellable() {
|
||||
return cancellable;
|
||||
}
|
||||
|
||||
void setCancellable(boolean cancellable) {
|
||||
this.cancellable = cancellable;
|
||||
}
|
||||
|
||||
public TaskId getParentTaskId() {
|
||||
return parentTaskId;
|
||||
}
|
||||
|
||||
void setParentTaskId(String parentTaskId) {
|
||||
this.parentTaskId = new TaskId(parentTaskId);
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
void setHeaders(Map<String, String> headers) {
|
||||
this.headers.putAll(headers);
|
||||
}
|
||||
|
||||
void setStatus(Map<String, Object> status) {
|
||||
this.status.putAll(status);
|
||||
}
|
||||
|
||||
public Map<String, Object> getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
private void noOpParse(Object s) {}
|
||||
|
||||
public static final ObjectParser.NamedObjectParser<TaskInfo, Void> PARSER;
|
||||
|
||||
static {
|
||||
ObjectParser<TaskInfo, Void> parser = new ObjectParser<>("tasks", true, null);
|
||||
// already provided in constructor: triggering a no-op
|
||||
parser.declareString(TaskInfo::noOpParse, new ParseField("node"));
|
||||
// already provided in constructor: triggering a no-op
|
||||
parser.declareLong(TaskInfo::noOpParse, new ParseField("id"));
|
||||
parser.declareString(TaskInfo::setType, new ParseField("type"));
|
||||
parser.declareString(TaskInfo::setAction, new ParseField("action"));
|
||||
parser.declareObject(TaskInfo::setStatus, (p, c) -> p.map(), new ParseField("status"));
|
||||
parser.declareString(TaskInfo::setDescription, new ParseField("description"));
|
||||
parser.declareLong(TaskInfo::setStartTime, new ParseField("start_time_in_millis"));
|
||||
parser.declareLong(TaskInfo::setRunningTimeNanos, new ParseField("running_time_in_nanos"));
|
||||
parser.declareBoolean(TaskInfo::setCancellable, new ParseField("cancellable"));
|
||||
parser.declareString(TaskInfo::setParentTaskId, new ParseField("parent_task_id"));
|
||||
parser.declareObject(TaskInfo::setHeaders, (p, c) -> p.mapStrings(), new ParseField("headers"));
|
||||
PARSER = (XContentParser p, Void v, String name) -> parser.parse(p, new TaskInfo(new TaskId(name)), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TaskInfo)) return false;
|
||||
TaskInfo taskInfo = (TaskInfo) o;
|
||||
return getStartTime() == taskInfo.getStartTime() &&
|
||||
getRunningTimeNanos() == taskInfo.getRunningTimeNanos() &&
|
||||
isCancellable() == taskInfo.isCancellable() &&
|
||||
Objects.equals(getTaskId(), taskInfo.getTaskId()) &&
|
||||
Objects.equals(getType(), taskInfo.getType()) &&
|
||||
Objects.equals(getAction(), taskInfo.getAction()) &&
|
||||
Objects.equals(getDescription(), taskInfo.getDescription()) &&
|
||||
Objects.equals(getParentTaskId(), taskInfo.getParentTaskId()) &&
|
||||
Objects.equals(status, taskInfo.status) &&
|
||||
Objects.equals(getHeaders(), taskInfo.getHeaders());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(
|
||||
getTaskId(), getType(), getAction(), getDescription(), getStartTime(),
|
||||
getRunningTimeNanos(), isCancellable(), getParentTaskId(), status, getHeaders()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TaskInfo{" +
|
||||
"taskId=" + taskId +
|
||||
", type='" + type + '\'' +
|
||||
", action='" + action + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", startTime=" + startTime +
|
||||
", runningTimeNanos=" + runningTimeNanos +
|
||||
", cancellable=" + cancellable +
|
||||
", parentTaskId=" + parentTaskId +
|
||||
", status=" + status +
|
||||
", headers=" + headers +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
|
||||
/**
|
||||
* client side counterpart of server side
|
||||
* {@link org.elasticsearch.action.TaskOperationFailure}
|
||||
*/
|
||||
public class TaskOperationFailure {
|
||||
|
||||
private final String nodeId;
|
||||
private final long taskId;
|
||||
private final ElasticsearchException reason;
|
||||
private final String status;
|
||||
|
||||
public TaskOperationFailure(String nodeId, long taskId,String status, ElasticsearchException reason) {
|
||||
this.nodeId = nodeId;
|
||||
this.taskId = taskId;
|
||||
this.status = status;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public long getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public ElasticsearchException getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TaskOperationFailure)) return false;
|
||||
TaskOperationFailure that = (TaskOperationFailure) o;
|
||||
return getTaskId() == that.getTaskId() &&
|
||||
Objects.equals(getNodeId(), that.getNodeId()) &&
|
||||
Objects.equals(getReason(), that.getReason()) &&
|
||||
Objects.equals(getStatus(), that.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getNodeId(), getTaskId(), getReason(), getStatus());
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TaskOperationFailure{" +
|
||||
"nodeId='" + nodeId + '\'' +
|
||||
", taskId=" + taskId +
|
||||
", reason=" + reason +
|
||||
", status='" + status + '\'' +
|
||||
'}';
|
||||
}
|
||||
public static TaskOperationFailure fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
private static final ConstructingObjectParser<TaskOperationFailure, Void> PARSER =
|
||||
new ConstructingObjectParser<>("task_info", true, constructorObjects -> {
|
||||
int i = 0;
|
||||
String nodeId = (String) constructorObjects[i++];
|
||||
long taskId = (long) constructorObjects[i++];
|
||||
String status = (String) constructorObjects[i++];
|
||||
ElasticsearchException reason = (ElasticsearchException) constructorObjects[i];
|
||||
return new TaskOperationFailure(nodeId, taskId, status, reason);
|
||||
});
|
||||
|
||||
static {
|
||||
PARSER.declareString(constructorArg(), new ParseField("node_id"));
|
||||
PARSER.declareLong(constructorArg(), new ParseField("task_id"));
|
||||
PARSER.declareString(constructorArg(), new ParseField("status"));
|
||||
PARSER.declareObject(constructorArg(), (parser, c) -> ElasticsearchException.fromXContent(parser), new ParseField("reason"));
|
||||
}
|
||||
}
|
|
@ -19,21 +19,20 @@
|
|||
|
||||
package org.elasticsearch.client;
|
||||
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksResponse;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.client.tasks.CancelTasksRequest;
|
||||
import org.elasticsearch.client.tasks.CancelTasksResponse;
|
||||
import org.elasticsearch.client.tasks.GetTaskRequest;
|
||||
import org.elasticsearch.client.tasks.GetTaskResponse;
|
||||
import org.elasticsearch.client.tasks.TaskId;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.tasks.TaskId;
|
||||
import org.elasticsearch.tasks.TaskInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
@ -58,12 +57,12 @@ public class TasksIT extends ESRestHighLevelClientTestCase {
|
|||
assertThat(response.getTasks().size(), greaterThanOrEqualTo(2));
|
||||
boolean listTasksFound = false;
|
||||
for (TaskGroup taskGroup : response.getTaskGroups()) {
|
||||
TaskInfo parent = taskGroup.getTaskInfo();
|
||||
org.elasticsearch.tasks.TaskInfo parent = taskGroup.getTaskInfo();
|
||||
if ("cluster:monitor/tasks/lists".equals(parent.getAction())) {
|
||||
assertThat(taskGroup.getChildTasks().size(), equalTo(1));
|
||||
TaskGroup childGroup = taskGroup.getChildTasks().iterator().next();
|
||||
assertThat(childGroup.getChildTasks().isEmpty(), equalTo(true));
|
||||
TaskInfo child = childGroup.getTaskInfo();
|
||||
org.elasticsearch.tasks.TaskInfo child = childGroup.getTaskInfo();
|
||||
assertThat(child.getAction(), equalTo("cluster:monitor/tasks/lists[n]"));
|
||||
assertThat(child.getParentTaskId(), equalTo(parent.getTaskId()));
|
||||
listTasksFound = true;
|
||||
|
@ -117,7 +116,7 @@ public class TasksIT extends ESRestHighLevelClientTestCase {
|
|||
if (gtr.getWaitForCompletion()) {
|
||||
assertTrue(taskResponse.isCompleted());
|
||||
}
|
||||
TaskInfo info = taskResponse.getTaskInfo();
|
||||
org.elasticsearch.tasks.TaskInfo info = taskResponse.getTaskInfo();
|
||||
assertTrue(info.isCancellable());
|
||||
assertEquals("reindex from [source1] to [dest][_doc]", info.getDescription());
|
||||
assertEquals("indices:data/write/reindex", info.getAction());
|
||||
|
@ -142,12 +141,12 @@ public class TasksIT extends ESRestHighLevelClientTestCase {
|
|||
);
|
||||
// in this case, probably no task will actually be cancelled.
|
||||
// this is ok, that case is covered in TasksIT.testTasksCancellation
|
||||
TaskInfo firstTask = listResponse.getTasks().get(0);
|
||||
org.elasticsearch.tasks.TaskInfo firstTask = listResponse.getTasks().get(0);
|
||||
String node = listResponse.getPerNodeTasks().keySet().iterator().next();
|
||||
|
||||
CancelTasksRequest cancelTasksRequest = new CancelTasksRequest();
|
||||
cancelTasksRequest.setTaskId(new TaskId(node, firstTask.getId()));
|
||||
cancelTasksRequest.setReason("testreason");
|
||||
CancelTasksRequest cancelTasksRequest = new CancelTasksRequest.Builder().withTaskId(
|
||||
new TaskId(node, firstTask.getId())
|
||||
).build();
|
||||
CancelTasksResponse response = execute(cancelTasksRequest,
|
||||
highLevelClient().tasks()::cancel,
|
||||
highLevelClient().tasks()::cancelAsync);
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.elasticsearch.client;
|
|||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
|
||||
import org.elasticsearch.tasks.TaskId;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
@ -36,12 +35,16 @@ import static org.hamcrest.Matchers.nullValue;
|
|||
public class TasksRequestConvertersTests extends ESTestCase {
|
||||
|
||||
public void testCancelTasks() {
|
||||
CancelTasksRequest request = new CancelTasksRequest();
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
TaskId taskId = new TaskId(randomAlphaOfLength(5), randomNonNegativeLong());
|
||||
TaskId parentTaskId = new TaskId(randomAlphaOfLength(5), randomNonNegativeLong());
|
||||
request.setTaskId(taskId);
|
||||
request.setParentTaskId(parentTaskId);
|
||||
org.elasticsearch.client.tasks.TaskId taskId =
|
||||
new org.elasticsearch.client.tasks.TaskId(randomAlphaOfLength(5), randomNonNegativeLong());
|
||||
org.elasticsearch.client.tasks.TaskId parentTaskId =
|
||||
new org.elasticsearch.client.tasks.TaskId(randomAlphaOfLength(5), randomNonNegativeLong());
|
||||
org.elasticsearch.client.tasks.CancelTasksRequest request =
|
||||
new org.elasticsearch.client.tasks.CancelTasksRequest.Builder()
|
||||
.withTaskId(taskId)
|
||||
.withParentTaskId(parentTaskId)
|
||||
.build();
|
||||
expectedParams.put("task_id", taskId.toString());
|
||||
expectedParams.put("parent_task_id", parentTaskId.toString());
|
||||
Request httpRequest = TasksRequestConverters.cancelTasks(request);
|
||||
|
|
|
@ -23,19 +23,21 @@ import org.elasticsearch.ElasticsearchException;
|
|||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.LatchedActionListener;
|
||||
import org.elasticsearch.action.TaskOperationFailure;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksResponse;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup;
|
||||
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.client.tasks.CancelTasksRequest;
|
||||
import org.elasticsearch.client.tasks.CancelTasksResponse;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.tasks.TaskId;
|
||||
import org.elasticsearch.tasks.TaskInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
@ -155,19 +157,21 @@ public class TasksClientDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
RestHighLevelClient client = highLevelClient();
|
||||
{
|
||||
// tag::cancel-tasks-request
|
||||
CancelTasksRequest request = new CancelTasksRequest();
|
||||
CancelTasksRequest request = new org.elasticsearch.client.tasks.CancelTasksRequest.Builder()
|
||||
.withNodesFiltered(Arrays.asList("nodeId1", "nodeId2"))
|
||||
.withActionsFiltered(Collections.singletonList("cluster:*"))
|
||||
.build();
|
||||
// end::cancel-tasks-request
|
||||
|
||||
// tag::cancel-tasks-request-filter
|
||||
request.setTaskId(new TaskId("nodeId1", 42)); //<1>
|
||||
request.setActions("cluster:*"); // <2>
|
||||
request.setNodes("nodeId1", "nodeId2"); // <3>
|
||||
CancelTasksRequest byTaskIdRequest = new org.elasticsearch.client.tasks.CancelTasksRequest.Builder() // <1>
|
||||
.withTaskId(new org.elasticsearch.client.tasks.TaskId("myNode",44L)) // <2>
|
||||
.build(); // <3>
|
||||
// end::cancel-tasks-request-filter
|
||||
|
||||
}
|
||||
|
||||
CancelTasksRequest request = new CancelTasksRequest();
|
||||
request.setTaskId(TaskId.EMPTY_TASK_ID);
|
||||
CancelTasksRequest request = new org.elasticsearch.client.tasks.CancelTasksRequest.Builder().build();
|
||||
|
||||
// tag::cancel-tasks-execute
|
||||
CancelTasksResponse response = client.tasks().cancel(request, RequestOptions.DEFAULT);
|
||||
|
@ -176,18 +180,18 @@ public class TasksClientDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
assertThat(response, notNullValue());
|
||||
|
||||
// tag::cancel-tasks-response-tasks
|
||||
List<TaskInfo> tasks = response.getTasks(); // <1>
|
||||
List<org.elasticsearch.client.tasks.TaskInfo> tasks = response.getTasks(); // <1>
|
||||
// end::cancel-tasks-response-tasks
|
||||
|
||||
// tag::cancel-tasks-response-calc
|
||||
Map<String, List<TaskInfo>> perNodeTasks = response.getPerNodeTasks(); // <1>
|
||||
List<TaskGroup> groups = response.getTaskGroups(); // <2>
|
||||
Map<String, List<org.elasticsearch.client.tasks.TaskInfo>> perNodeTasks = response.getPerNodeTasks(); // <1>
|
||||
List<org.elasticsearch.client.tasks.TaskGroup> groups = response.getTaskGroups(); // <2>
|
||||
// end::cancel-tasks-response-calc
|
||||
|
||||
|
||||
// tag::cancel-tasks-response-failures
|
||||
List<ElasticsearchException> nodeFailures = response.getNodeFailures(); // <1>
|
||||
List<TaskOperationFailure> taskFailures = response.getTaskFailures(); // <2>
|
||||
List<org.elasticsearch.client.tasks.ElasticsearchException> nodeFailures = response.getNodeFailures(); // <1>
|
||||
List<org.elasticsearch.client.tasks.TaskOperationFailure> taskFailures = response.getTaskFailures(); // <2>
|
||||
// end::cancel-tasks-response-failures
|
||||
|
||||
assertThat(response.getNodeFailures(), equalTo(emptyList()));
|
||||
|
@ -198,7 +202,7 @@ public class TasksClientDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
{
|
||||
CancelTasksRequest request = new CancelTasksRequest();
|
||||
CancelTasksRequest request = new org.elasticsearch.client.tasks.CancelTasksRequest.Builder().build();
|
||||
|
||||
// tag::cancel-tasks-execute-listener
|
||||
ActionListener<CancelTasksResponse> listener =
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.TaskOperationFailure;
|
||||
import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksResponse;
|
||||
import org.elasticsearch.client.AbstractResponseTestCase;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.tasks.Task;
|
||||
import org.elasticsearch.tasks.TaskId;
|
||||
import org.elasticsearch.tasks.TaskInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
public class CancelTasksResponseTests extends AbstractResponseTestCase<CancelTasksResponseTests.ByNodeCancelTasksResponse,
|
||||
org.elasticsearch.client.tasks.CancelTasksResponse> {
|
||||
|
||||
private static String NODE_ID = "node_id";
|
||||
|
||||
@Override
|
||||
protected CancelTasksResponseTests.ByNodeCancelTasksResponse createServerTestInstance(XContentType xContentType) {
|
||||
List<org.elasticsearch.tasks.TaskInfo> tasks = new ArrayList<>();
|
||||
List<TaskOperationFailure> taskFailures = new ArrayList<>();
|
||||
List<ElasticsearchException> nodeFailures = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < randomIntBetween(1, 4); i++) {
|
||||
taskFailures.add(new TaskOperationFailure(randomAlphaOfLength(4), (long) i,
|
||||
new RuntimeException(randomAlphaOfLength(4))));
|
||||
}
|
||||
for (int i = 0; i < randomIntBetween(1, 4); i++) {
|
||||
nodeFailures.add(new ElasticsearchException(new RuntimeException(randomAlphaOfLength(10))));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tasks.add(new org.elasticsearch.tasks.TaskInfo(
|
||||
new TaskId(NODE_ID, (long) i),
|
||||
randomAlphaOfLength(4),
|
||||
randomAlphaOfLength(4),
|
||||
randomAlphaOfLength(10),
|
||||
new FakeTaskStatus(randomAlphaOfLength(4), randomInt()),
|
||||
randomLongBetween(1, 3),
|
||||
randomIntBetween(5, 10),
|
||||
false,
|
||||
new TaskId("node1", randomLong()),
|
||||
Collections.singletonMap("x-header-of", "some-value")));
|
||||
}
|
||||
|
||||
return new ByNodeCancelTasksResponse(tasks, taskFailures, nodeFailures);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected org.elasticsearch.client.tasks.CancelTasksResponse doParseToClientInstance(XContentParser parser) throws IOException {
|
||||
return org.elasticsearch.client.tasks.CancelTasksResponse.fromXContent(parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertInstances(ByNodeCancelTasksResponse serverTestInstance,
|
||||
org.elasticsearch.client.tasks.CancelTasksResponse clientInstance) {
|
||||
|
||||
// checking tasks
|
||||
List<TaskInfo> sTasks = serverTestInstance.getTasks();
|
||||
List<org.elasticsearch.client.tasks.TaskInfo> cTasks = clientInstance.getTasks();
|
||||
Map<org.elasticsearch.client.tasks.TaskId, org.elasticsearch.client.tasks.TaskInfo> cTasksMap =
|
||||
cTasks.stream().collect(Collectors.toMap(org.elasticsearch.client.tasks.TaskInfo::getTaskId,
|
||||
Function.identity()));
|
||||
for (TaskInfo ti : sTasks) {
|
||||
org.elasticsearch.client.tasks.TaskInfo taskInfo = cTasksMap.get(
|
||||
new org.elasticsearch.client.tasks.TaskId(ti.getTaskId().getNodeId(), ti.getTaskId().getId())
|
||||
);
|
||||
assertEquals(ti.getAction(), taskInfo.getAction());
|
||||
assertEquals(ti.getDescription(), taskInfo.getDescription());
|
||||
assertEquals(new HashMap<>(ti.getHeaders()), new HashMap<>(taskInfo.getHeaders()));
|
||||
assertEquals(ti.getType(), taskInfo.getType());
|
||||
assertEquals(ti.getStartTime(), taskInfo.getStartTime());
|
||||
assertEquals(ti.getRunningTimeNanos(), taskInfo.getRunningTimeNanos());
|
||||
assertEquals(ti.isCancellable(), taskInfo.isCancellable());
|
||||
assertEquals(ti.getParentTaskId().getNodeId(), taskInfo.getParentTaskId().getNodeId());
|
||||
assertEquals(ti.getParentTaskId().getId(), taskInfo.getParentTaskId().getId());
|
||||
FakeTaskStatus status = (FakeTaskStatus) ti.getStatus();
|
||||
assertEquals(status.code, taskInfo.getStatus().get("code"));
|
||||
assertEquals(status.status, taskInfo.getStatus().get("status"));
|
||||
|
||||
}
|
||||
|
||||
//checking failures
|
||||
List<ElasticsearchException> serverNodeFailures = serverTestInstance.getNodeFailures();
|
||||
List<org.elasticsearch.client.tasks.ElasticsearchException> cNodeFailures = clientInstance.getNodeFailures();
|
||||
List<String> sExceptionsMessages = serverNodeFailures.stream().map(x ->
|
||||
org.elasticsearch.client.tasks.ElasticsearchException.buildMessage(
|
||||
"exception", x.getMessage(), null)
|
||||
).collect(Collectors.toList()
|
||||
);
|
||||
|
||||
List<String> cExceptionsMessages = cNodeFailures.stream().map(
|
||||
org.elasticsearch.client.tasks.ElasticsearchException::getMsg
|
||||
).collect(Collectors.toList());
|
||||
assertEquals(new HashSet<>(sExceptionsMessages), new HashSet<>(cExceptionsMessages));
|
||||
|
||||
List<TaskOperationFailure> sTaskFailures = serverTestInstance.getTaskFailures();
|
||||
List<org.elasticsearch.client.tasks.TaskOperationFailure> cTaskFailures = clientInstance.getTaskFailures();
|
||||
|
||||
Map<Long, org.elasticsearch.client.tasks.TaskOperationFailure> cTasksFailuresMap =
|
||||
cTaskFailures.stream().collect(Collectors.toMap(
|
||||
org.elasticsearch.client.tasks.TaskOperationFailure::getTaskId,
|
||||
Function.identity()));
|
||||
for (TaskOperationFailure tof : sTaskFailures) {
|
||||
org.elasticsearch.client.tasks.TaskOperationFailure failure = cTasksFailuresMap.get(tof.getTaskId());
|
||||
assertEquals(tof.getNodeId(), failure.getNodeId());
|
||||
assertTrue(failure.getReason().getMsg().contains("runtime_exception"));
|
||||
assertTrue(failure.getStatus().contains("" + tof.getStatus().name()));
|
||||
}
|
||||
}
|
||||
|
||||
public static class FakeTaskStatus implements Task.Status {
|
||||
|
||||
final String status;
|
||||
final int code;
|
||||
|
||||
public FakeTaskStatus(String status, int code) {
|
||||
this.status = status;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWriteableName() {
|
||||
return "faker";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(status);
|
||||
out.writeInt(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field("status", status);
|
||||
builder.field("code", code);
|
||||
return builder.endObject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tasks are grouped under nodes, and in order to create DiscoveryNodes we need different
|
||||
* IP addresses.
|
||||
* So in this test we assume all tasks are issued by a single node whose name and IP address is hardcoded.
|
||||
*/
|
||||
static class ByNodeCancelTasksResponse extends CancelTasksResponse {
|
||||
|
||||
ByNodeCancelTasksResponse(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
ByNodeCancelTasksResponse(
|
||||
List<TaskInfo> tasks,
|
||||
List<TaskOperationFailure> taskFailures,
|
||||
List<? extends ElasticsearchException> nodeFailures) {
|
||||
super(tasks, taskFailures, nodeFailures);
|
||||
}
|
||||
|
||||
|
||||
// it knows the hardcoded address space.
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
|
||||
DiscoveryNodes.Builder dnBuilder = new DiscoveryNodes.Builder();
|
||||
InetAddress inetAddress = InetAddress.getByAddress(new byte[]{(byte) 192, (byte) 168, (byte) 0, (byte) 1});
|
||||
TransportAddress transportAddress = new TransportAddress(inetAddress, randomIntBetween(0, 65535));
|
||||
|
||||
dnBuilder.add(new DiscoveryNode(NODE_ID, NODE_ID, transportAddress, emptyMap(), emptySet(), Version.CURRENT));
|
||||
|
||||
DiscoveryNodes build = dnBuilder.build();
|
||||
builder.startObject();
|
||||
super.toXContentGroupedByNode(builder, params, build);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.client.tasks;
|
||||
|
||||
import org.elasticsearch.client.AbstractResponseTestCase;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
public class ElasticsearchExceptionTests extends AbstractResponseTestCase<org.elasticsearch.ElasticsearchException,
|
||||
org.elasticsearch.client.tasks.ElasticsearchException> {
|
||||
|
||||
@Override
|
||||
protected org.elasticsearch.ElasticsearchException createServerTestInstance(XContentType xContentType) {
|
||||
IllegalStateException ies = new IllegalStateException("illegal_state");
|
||||
IllegalArgumentException iae = new IllegalArgumentException("argument", ies);
|
||||
org.elasticsearch.ElasticsearchException exception = new org.elasticsearch.ElasticsearchException("elastic_exception", iae);
|
||||
exception.addHeader("key","value");
|
||||
exception.addMetadata("es.meta","data");
|
||||
exception.addSuppressed(new NumberFormatException("3/0"));
|
||||
return exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ElasticsearchException doParseToClientInstance(XContentParser parser) throws IOException {
|
||||
parser.nextToken();
|
||||
return ElasticsearchException.fromXContent(parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertInstances(org.elasticsearch.ElasticsearchException serverTestInstance, ElasticsearchException clientInstance) {
|
||||
|
||||
IllegalArgumentException sCauseLevel1 = (IllegalArgumentException) serverTestInstance.getCause();
|
||||
ElasticsearchException cCauseLevel1 = clientInstance.getCause();
|
||||
|
||||
assertTrue(sCauseLevel1 !=null);
|
||||
assertTrue(cCauseLevel1 !=null);
|
||||
|
||||
IllegalStateException causeLevel2 = (IllegalStateException) serverTestInstance.getCause().getCause();
|
||||
ElasticsearchException cCauseLevel2 = clientInstance.getCause().getCause();
|
||||
assertTrue(causeLevel2 !=null);
|
||||
assertTrue(cCauseLevel2 !=null);
|
||||
|
||||
|
||||
ElasticsearchException cause = new ElasticsearchException(
|
||||
"Elasticsearch exception [type=illegal_state_exception, reason=illegal_state]"
|
||||
);
|
||||
ElasticsearchException caused1 = new ElasticsearchException(
|
||||
"Elasticsearch exception [type=illegal_argument_exception, reason=argument]",cause
|
||||
);
|
||||
ElasticsearchException caused2 = new ElasticsearchException(
|
||||
"Elasticsearch exception [type=exception, reason=elastic_exception]",caused1
|
||||
);
|
||||
|
||||
caused2.addHeader("key", Collections.singletonList("value"));
|
||||
ElasticsearchException supp = new ElasticsearchException(
|
||||
"Elasticsearch exception [type=number_format_exception, reason=3/0]"
|
||||
);
|
||||
caused2.addSuppressed(Collections.singletonList(supp));
|
||||
|
||||
assertEquals(caused2,clientInstance);
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue