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

Add delete API to the High Level Rest Client #23187

Merged
merged 12 commits into from Feb 24, 2017

Conversation

dadoonet
Copy link
Member

No description provided.

assertEquals("type", deleteResponse.getType());
assertEquals("does_not_exist", deleteResponse.getId());
assertEquals(DocWriteResponse.Result.NOT_FOUND, deleteResponse.getResult());
assertEquals(1, deleteResponse.getVersion());
Copy link
Member Author

Choose a reason for hiding this comment

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

This is surprising to me. I'd expect it to be -1 similar to the GET request

Copy link
Member

Choose a reason for hiding this comment

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

I think Get request returns an error with NOT FOUND response code in this case? Which make more sense to me.

Anyway a delete increments the version even if the document is not found, and is kept in the versions map as a tombstone.

# Conflicts:
#	client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java
#	client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java
@dadoonet dadoonet requested a review from tlrx February 16, 2017 08:59
@@ -118,6 +120,21 @@ static Request index(IndexRequest indexRequest) {
return new Request(method, endpoint, parameters.getParams(), entity);
}

static Request delete(DeleteRequest deleteRequest) {
Copy link
Member

Choose a reason for hiding this comment

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

Can you please move this up so that methods are somewhat alphabetically sorted?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok. I'm also moving ping method. And add a comments for coming developers

@@ -121,6 +123,22 @@ public void indexAsync(IndexRequest indexRequest, ActionListener<IndexResponse>
performRequestAsyncAndParseEntity(indexRequest, Request::index, IndexResponse::fromXContent, listener, emptySet(), headers);
}

/**
* Deletes a document by id using the delete api
Copy link
Member

Choose a reason for hiding this comment

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

"Deletes a document using the Delete API" with a link to the documentation like it is done for other methods

Copy link
Member Author

Choose a reason for hiding this comment

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

Right. I did not notice the modifications when I merged the master branch into my branch.

/**
* Asynchronously deletes a document by id using the delete api
*/
public void deleteAsync(DeleteRequest deleteRequest, ActionListener<DeleteResponse> listener, Header... headers) {
Copy link
Member

Choose a reason for hiding this comment

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

Same here for javadoc

assertEquals("index", deleteResponse.getIndex());
assertEquals("type", deleteResponse.getType());
assertEquals("id", deleteResponse.getId());
assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
Copy link
Member

Choose a reason for hiding this comment

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

I don't see tests for routing, parent, version type etc. That would be nice to check that parameters are correctly propagated.

String document = "{\"field1\":\"value1\",\"field2\":\"value2\"}";
StringEntity stringEntity = new StringEntity(document, ContentType.APPLICATION_JSON);
Response response = client().performRequest("PUT", "/index/type/id", Collections.singletonMap("refresh", "wait_for"), stringEntity);
assertEquals(201, response.getStatusLine().getStatusCode());
Copy link
Member

Choose a reason for hiding this comment

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

I think we could start using our own high level rest client for those? Now we have Index API support...

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed.

@@ -265,4 +267,40 @@ public void testIndex() throws IOException {
"version conflict, document already exists (current version [1])]", exception.getMessage());
}
}

public void testDelete() throws IOException {
Copy link
Member

Choose a reason for hiding this comment

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

Can you move this up so that it is alphabetically sorted?

assertEquals("type", deleteResponse.getType());
assertEquals("does_not_exist", deleteResponse.getId());
assertEquals(DocWriteResponse.Result.NOT_FOUND, deleteResponse.getResult());
assertEquals(1, deleteResponse.getVersion());
Copy link
Member

Choose a reason for hiding this comment

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

I think Get request returns an error with NOT FOUND response code in this case? Which make more sense to me.

Anyway a delete increments the version even if the document is not found, and is kept in the versions map as a tombstone.

* Sort alphabetically method names
* Add javadoc link to the ref guide
* Add more tests about routing, version and version type
@dadoonet
Copy link
Member Author

Thanks @tlrx for the review!

I pushed a new commit to address your comments. LMK.

Copy link
Member

@javanna javanna left a comment

Choose a reason for hiding this comment

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

left a few comments LGTM otherwise

@@ -69,8 +71,21 @@ public String toString() {
'}';
}

static Request ping() {
return new Request("HEAD", "/", Collections.emptyMap(), null);
// For developers please add your new methods in the alphabetical order
Copy link
Member

Choose a reason for hiding this comment

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

I think this comment won't be enough to enforce this convention... why does order matter anyways @tlrx ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed. But at least as I was not aware of this convention and did not find it in code comments I added it.
Any suggestion? Remove the comment?

Copy link
Member

Choose a reason for hiding this comment

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

@javanna It doesn't matter, that's not a convention and it doesn't make sense to add a comment for that. I just find it easier to find and read class methods when they are sorted, specially when it's a suite of operations like this. But if I'm the only one to care about this, let's add new method wherever you want.

Copy link
Member

Choose a reason for hiding this comment

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

ok let's remove the comment.

* @return A sample index request
* @throws IOException If problem when generating the content
*/
private IndexRequest createSampleIndexRequest() throws IOException {
Copy link
Member

Choose a reason for hiding this comment

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

do we need a method for this? don't we always do createSampleDocument(createSampleIndexRequest))?

I also wonder if it's ok to always rely on auto-generated ids. maybe we should provide our ids instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

don't we always do createSampleDocument(createSampleIndexRequest))?

No. We also do:

createSampleDocument(createSampleIndexRequest().routing("foo"));

See

String docId = createSampleDocument(createSampleIndexRequest().routing("foo"));

Copy link
Member Author

@dadoonet dadoonet Feb 20, 2017

Choose a reason for hiding this comment

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

I also wonder if it's ok to always rely on auto-generated ids. maybe we should provide our ids instead.

Why not?

note that sometimes I'm doing:

createSampleIndexRequest().id(randomAsciiOfLength(15));

Where I basically force the id. So I'd say that we have both covered.

Copy link
Member

Choose a reason for hiding this comment

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

that's ok. anyways we are testing delete here.

Copy link
Member Author

Choose a reason for hiding this comment

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

So I'm now using my own ids for every test.

parameters.withRefreshPolicy(deleteRequest.getRefreshPolicy());
parameters.withWaitForActiveShards(deleteRequest.waitForActiveShards());

return new Request(HttpDelete.METHOD_NAME, endpoint, parameters.getParams(), null);
Copy link
Member

Choose a reason for hiding this comment

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

I think we should test this in RequestTests and have unit tests to make sure that all supported parameters are propagated.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you want to test the Params builder actually?

Something like:

    public void testWithParams() {
        Request.Params params = Request.Params.builder();
        params.withFetchSourceContext(FetchSourceContext.FETCH_SOURCE);
        params.withParent("parent");
        params.withPipeline("pipeline");
        params.withPreference("preference");
        params.withRealtime(true);
        if (randomBoolean()) {
            params.withRefresh(true);
        } else {
            params.withRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
        }
        params.withRouting("routing");
        params.withStoredFields(new String[]{"field1","field2"});
        params.withTimeout(TimeValue.timeValueMillis(100));
        params.withVersion(2);
        params.withVersionType(VersionType.EXTERNAL);
        params.withWaitForActiveShards(ActiveShardCount.ALL);
        Map<String, String> requestParams = params.getParams();
        assertEquals(10, requestParams.size());
    }

I can add it in the PR or later.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think the above is that useful, I would rather like to make sure that the new method to generate a request calls all of the with* methods that need to be called and the params from map to request are all propagated.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I understand. So test something like the following?

    public void testDelete() {
        DeleteRequest deleteRequest = new DeleteRequest("index", "type", "id")
            .routing("routing");

        Request request = Request.delete(deleteRequest);
        assertEquals(true, request.params.containsKey("routing"));
    }

Copy link
Member

Choose a reason for hiding this comment

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

yes something along those lines. we have existing tests for this in RequestTests, see e.g. testIndex

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the pointer. I did that in RequestTests.

private IndexRequest createSampleIndexRequest() throws IOException {
final XContentType xContentType = randomFrom(XContentType.values());
IndexRequest indexRequest = new IndexRequest("index", "type");
indexRequest.source(XContentBuilder.builder(xContentType.xContent()).startObject().field("test", "test").endObject());
Copy link
Member

Choose a reason for hiding this comment

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

if this is only used for testing deletions, I don't think we need to randomize the content type when indexing. Let's use json? we can also provide it as a string.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed. I simplified all that.

@dadoonet
Copy link
Member Author

@javanna @tlrx I think I addressed your comments. Wanna review one more time?

* @throws IOException if something goes wrong while executing the index request
*/
private void createSampleDocument(IndexRequest request) throws IOException {
IndexResponse indexResponse = execute(request, highLevelClient()::index, highLevelClient()::indexAsync);
Copy link
Member

Choose a reason for hiding this comment

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

one more thing, given that this is used only to test deletions, let's just use the sync version of the method rather than randomizing. I do wonder whether this additional method is needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

If we do only the sync method, then we can definitely remove that method IMO. I'll do that.

expectedParams.put("timeout", ReplicationRequest.DEFAULT_TIMEOUT.getStringRep());
}

if (frequently()) {
Copy link
Member

Choose a reason for hiding this comment

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

out of curiosity, why frequently and not e.g. half of the times?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy and paste from index test. I can change it in both places or only here. As you prefer.

expectedParams.put("refresh", refreshPolicy.getValue());
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

maybe we can share some common parts between index and delete?

Copy link
Member Author

Choose a reason for hiding this comment

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

Haha! Funny. I wanted to propose that but was unsure. I totally agree.

@dadoonet
Copy link
Member Author

@javanna @tlrx Any other thoughts?

Copy link
Member

@tlrx tlrx left a comment

Choose a reason for hiding this comment

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

I left some more comments I'd like to see merged in. Otherwise it's ok, thanks @dadoonet

() -> execute(deleteRequest, highLevelClient()::delete, highLevelClient()::deleteAsync));
assertEquals(RestStatus.CONFLICT, exception.status());
assertEquals("Elasticsearch exception [type=version_conflict_engine_exception, " +
"reason=[type][" + docId + "]: " +
Copy link
Member

Choose a reason for hiding this comment

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

The format of the line seems a bit weird

Request request = Request.delete(deleteRequest);
assertEquals("/" + index + "/" + type + "/" + id, request.endpoint);
assertEquals(expectedParams, request.params);
assertEquals("DELETE", request.method);
Copy link
Member

Choose a reason for hiding this comment

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

Can you check that the request entity is null as well?


private void enrichReplicationRequest(ReplicatedWriteRequest request, Map<String, String> expectedParams) {
Copy link
Member

Choose a reason for hiding this comment

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

I'd have different static methods setRandomTimeout(..) and setRandomRefreshPolicy(...)

}

private void enrichDocWriteRequest(DocWriteRequest request, Map<String, String> expectedParams) {
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer to have two static methods setRandomVersion() and setRandomVersionType

private void enrichDocWriteRequest(DocWriteRequest request, Map<String, String> expectedParams) {
// There is some logic around _create endpoint and version/version type
if (request.opType() == DocWriteRequest.OpType.CREATE) {
Copy link
Member

Choose a reason for hiding this comment

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

This part should be in the testIndex() method because it is specific to Index requests, it could be:

public void testIndex()  {
    ...
    if (request.opType() == DocWriteRequest.OpType.CREATE) {
        ...
    } else {
        setRandomVersion(indexRequest, expectedParams);
        setRandomVersionType(indexRequest, expectedParams);
        ...
   }

@elasticmachine
Copy link
Collaborator

Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually?

@javanna
Copy link
Member

javanna commented Feb 23, 2017

@dadoonet can you merge this please? it's ready no?

@dadoonet
Copy link
Member Author

I hope doing it tomorrow morning CET.

# Conflicts:
#	client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java
#	client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
#	client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java
#	client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java
@dadoonet
Copy link
Member Author

Thanks Tanguy. That makes the code much more readable. I like it!

I think I should now have one more step which is to try to use all the randomXXX() methods I have to the other tests.
WDYT?

@tlrx
Copy link
Member

tlrx commented Feb 24, 2017

@dadoonet I think this can go in. Feel free to create a follow up pull request to apply randomVersion() etc to other tests.

@dadoonet dadoonet merged commit 3e4b917 into elastic:master Feb 24, 2017
@dadoonet dadoonet deleted the hlclient/add-delete-method branch February 24, 2017 10:57
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.

None yet

5 participants