Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLRC support for getTask #35166

Merged
merged 9 commits into from
Nov 12, 2018
Merged

Conversation

markharwood
Copy link
Contributor

@markharwood markharwood commented Nov 1, 2018

Given a GetTaskRequest the API returns an Optional which is empty in the case of 404s or returns a GetTaskResponse object if found.
Also added Helper methods in RestHighLevelClient for returning empty Optionals when hitting 404s as discussed here

Relates to #27205

@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra

@markharwood markharwood force-pushed the fix/27205getTask branch 2 times, most recently from c5ec7ea to b3d2af0 Compare November 5, 2018 09:50
@markharwood markharwood removed the WIP label Nov 5, 2018
@markharwood markharwood requested a review from hub-cap November 5, 2018 13:47
this.nodeId = nodeId;
this.taskId = taskId;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some redundant empty lines here, can we remove them?

public static GetTaskResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some minor new lines formatting would be nice to fix

request.setJsonEntity("{" + " \"source\": {\n" + " \"index\": \"source1\"\n" + " },\n" + " \"dest\": {\n"
+ " \"index\": \"dest\"\n" + " }" + "}");
Response response = lowClient.performRequest(request);
String responseBody = EntityUtils.toString(response.getEntity());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to use entityAsMap - available from super dlass

TaskId childTaskId = new TaskId(taskId.toString());
GetTaskRequest gtr = new GetTaskRequest(childTaskId.getNodeId(), childTaskId.getId());
Optional<GetTaskResponse> getTaskResponse = execute(gtr, highLevelClient().tasks()::get, highLevelClient().tasks()::getAsync);
assertTrue(getTaskResponse.isPresent());
Copy link
Contributor

@pgomulka pgomulka Nov 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this or assertions below might become flakey as there is no guarantee that the task will finish so quickly
would you consider waiting here for the status to finish?

    BooleanSupplier hasUpgradeCompleted = checkCompletionStatus(task);
            awaitBusy(hasUpgradeCompleted);
        }
    }
     private BooleanSupplier checkCompletionStatus(TaskId taskId) {
        return () -> {
            try {
                Response response = client().performRequest(new Request("GET", "/_tasks/" + taskId.toString()));
                return (boolean) entityAsMap(response).get("completed");
            } catch (IOException e) {
                fail(e.getMessage());
                return false;
            }
        };
    }

have a look at my draft https://github.com/elastic/elasticsearch/pull/35202/files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that a problem? My test is only asserting that the taskID exists and has the right description. The status (completed Vs in-progress) is not assumed and presumably it's beneficial for the test to potentially exercise both scenarios?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair point, but is this guaranteed that Optional.isPresent will always pass? I think it is possible that with unlucky timing the task will not be created by the time we call getTaskResponse

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as we discussed, that would be impossible to get an ID without a resource on already being created, loooks good!

Copy link
Contributor

@pgomulka pgomulka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very good to me, but left some minor comments

try {
response = client.performRequest(req);
} catch (ResponseException e) {
if (404 == e.getResponse().getStatusLine().getStatusCode()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use RestStatus.NOT_FOUND.getStatus() here instead of just 404. The async method will need to be updated too.

client.performRequestAsync(req, responseListener);
}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra line

@@ -1387,6 +1387,39 @@ public final void fieldCapsAsync(FieldCapabilitiesRequest fieldCapabilitiesReque
throw new IOException("Unable to parse response body for " + response, e);
}
}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra line

assertThat("the return type for method [" + method + "] is incorrect",
method.getReturnType().getSimpleName(), endsWith("Response"));
// It's acceptable for 404s to be represented as empty Optionals
if (!method.getReturnType().isAssignableFrom(Optional.class)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we ensure that the thing in the optional endsWith("Response"), as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did have a stab at that and I'm not sure I can get at it via reflection. The best I could get was that the Optional class used in the response has a generic type of T. I suspect type erasure might prevent me from seeing that level of detail at runtime.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i was unsure myself :)

import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;

public class GetTaskResponse {
private final boolean completed;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spacing is messed up here and below the getters

public Optional<GetTaskResponse> get(GetTaskRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseOptionalEntity(request, TasksRequestConverters::getTask, options,
GetTaskResponse::fromXContent);

Copy link
Contributor

@hub-cap hub-cap Nov 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spaces extra line

restHighLevelClient.performRequestAsyncAndParseOptionalEntity(request, TasksRequestConverters::getTask, options,
GetTaskResponse::fromXContent, listener);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra line

@@ -54,4 +55,12 @@ static Request listTasks(ListTasksRequest listTaskRequest) {
.putParam("group_by", "none");
return request;
}

static Request getTask(GetTaskRequest getTaskRequest) {
Request request = new Request(HttpGet.METHOD_NAME, "_tasks/" + getTaskRequest.getNodeId() + ":" + getTaskRequest.getTaskId());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use the EndpointBuilder here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also added a method to EndpointBuilder for colon separated parts

static Request getTask(GetTaskRequest getTaskRequest) {
Request request = new Request(HttpGet.METHOD_NAME, "_tasks/" + getTaskRequest.getNodeId() + ":" + getTaskRequest.getTaskId());
RequestConverters.Params params = new RequestConverters.Params(request);
params.withTimeout(getTaskRequest.getTimeout()).withWaitForCompletion(getTaskRequest.getWaitForCompletion());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can u put these on 2 lines? u can keep builder if u want, its just easier to see it split on 2 lines

@markharwood markharwood force-pushed the fix/27205getTask branch 2 times, most recently from d8665bf to 753677c Compare November 6, 2018 16:20
Copy link
Contributor

@hub-cap hub-cap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nits. i dont need to see it again.


static Request getTask(GetTaskRequest getTaskRequest) {
String endpoint = new EndpointBuilder().addPathPartAsIs("_tasks")
.addColonSeparatedPathParts(getTaskRequest.getNodeId(), Long.toString(getTaskRequest.getTaskId()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking this couldve just been a

.addPathPart(getTaskRequest.getNodeId() + ":" + Long.toString(getTaskRequest.getTaskId()))

since its technically one "path part" in a URL. Then there is no need for an extra method there. I was just trying to ensure we were using the EndpointBuilder in all the RequestConverters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I saw a precedent for comma-delimited parts in EndPointBuilder and assumed colon-delimited would be another variant. I guess it's not that common a convention so I removed it.

}

/**
* Timeout to wait for any async actions this request must take. It must take anywhere from 0 to 2.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure i like these comments.. I know they are in server, but what does "it must take anywhere from 0 to 2" mean...?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if there is a upper bound, maybe we should validate it in validate()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a copy-and-paste from the server equivalent. I'll take a closer look

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the comment. I don't see any validation code related to it so did not add anything to a validate() method. (General note: if we duplicate validation logic client and server-side is that not trappy code-maintenance-wise?)

@@ -1014,6 +1014,11 @@ EndpointBuilder addPathPart(String... parts) {
return this;
}

EndpointBuilder addColonSeparatedPathParts(String... parts) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im not sure this is needed, we can handle it in the method.

@hub-cap
Copy link
Contributor

hub-cap commented Nov 6, 2018

after approving, I realized we did not have a GetTaskResponseTest, which would use the AbstractXContentTestCase.xContentTester. Id be happy to look at it again once you create the test, or you can just merge it.

@markharwood markharwood force-pushed the fix/27205getTask branch 2 times, most recently from fe38da3 to 3fc4226 Compare November 9, 2018 11:08
Given a GetTaskRequest the API returns an Optional which is empty in the case of 404s or returns a TaskInfo object if found.
Added Helper methods in RestHighLevelClient for returning empty Optionals when hitting 404s
@markharwood markharwood merged commit 64e5c25 into elastic:master Nov 12, 2018
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Nov 12, 2018
* master:
  Address handling of OS pretty name on some OS (elastic#35451)
  HLRC support for getTask (elastic#35166)
  upgrade to lucene-8.0.0-snapshot-6d9c714052 (elastic#35428)
  Add docs for CCR stats API (elastic#35439)
  Fix the names of CCR stats endpoints in usage API (elastic#35438)
  Switch to default to no build qualifier (elastic#35415)
  Clarify S3 repository storage class parameter (elastic#35400)
  SQL: Fix query translation for scripted queries (elastic#35408)
  [TEST] Instead of ignoring the ccr downgrade to basic license qa test avoid the assertions that check the log files, because that does not work on Windows. The rest of the test is still useful and should work on Windows CI.
  Upgrade to Joda 2.10.1 (elastic#35410)
  HLRest: model role and privileges (elastic#35128)
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Nov 12, 2018
* master:
  Address handling of OS pretty name on some OS (elastic#35451)
  HLRC support for getTask (elastic#35166)
  upgrade to lucene-8.0.0-snapshot-6d9c714052 (elastic#35428)
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Nov 13, 2018
* master: (22 commits)
  Introduce CCR getting started guide (elastic#35434)
  Correct typo in BuildPlugin exception message (elastic#35458)
  Correct implemented interface of ParsedReverseNested (elastic#35455)
  [ML] Fix find_file_structure NPE with should_trim_fields (elastic#35465)
  Handle OS pretty name on old OS without OS release (elastic#35453)
  Register remote cluster compress setting (elastic#35464)
  [DOCS] Clarify results_index_name description (elastic#35463)
  [TEST] add missing doc tests for HLRC GetRollupIndexCaps API
  [HLRC] Add GetRollupIndexCaps API (elastic#35102)
  Geo: enables coerce support in WKT polygon parser (elastic#35414)
  [ILM] fix retry so it picks up latest policy and executes async action (elastic#35406)
  Address handling of OS pretty name on some OS (elastic#35451)
  HLRC support for getTask (elastic#35166)
  upgrade to lucene-8.0.0-snapshot-6d9c714052 (elastic#35428)
  Add docs for CCR stats API (elastic#35439)
  Fix the names of CCR stats endpoints in usage API (elastic#35438)
  Switch to default to no build qualifier (elastic#35415)
  Clarify S3 repository storage class parameter (elastic#35400)
  SQL: Fix query translation for scripted queries (elastic#35408)
  [TEST] Instead of ignoring the ccr downgrade to basic license qa test avoid the assertions that check the log files, because that does not work on Windows. The rest of the test is still useful and should work on Windows CI.
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants