mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-13 00:15:47 +00:00
[REST] Missing scroll id now returns 404
A bad/non-existing scroll ID used to return a 200, however a 404 might be more useful. Also, this PR returns the right Exception (SearchContextMissingException) in the Java API. Additionally: Added StatusToXContent interface and RestStatusToXContentListener listener, so the appropriate RestStatus can be returned Closes #5729
This commit is contained in:
parent
fad5e2d0e1
commit
d356881664
@ -29,7 +29,6 @@
|
|||||||
scroll_id: $scroll_id1
|
scroll_id: $scroll_id1
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
|
catch: missing
|
||||||
scroll:
|
scroll:
|
||||||
scroll_id: $scroll_id1
|
scroll_id: $scroll_id1
|
||||||
|
|
||||||
- length: {hits.hits: 0}
|
|
||||||
|
@ -23,10 +23,7 @@ import org.elasticsearch.action.ActionResponse;
|
|||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.*;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilderString;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
|
||||||
import org.elasticsearch.rest.RestStatus;
|
import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.search.SearchHits;
|
import org.elasticsearch.search.SearchHits;
|
||||||
import org.elasticsearch.search.aggregations.Aggregations;
|
import org.elasticsearch.search.aggregations.Aggregations;
|
||||||
@ -42,7 +39,7 @@ import static org.elasticsearch.search.internal.InternalSearchResponse.readInter
|
|||||||
/**
|
/**
|
||||||
* A response of a search request.
|
* A response of a search request.
|
||||||
*/
|
*/
|
||||||
public class SearchResponse extends ActionResponse implements ToXContent {
|
public class SearchResponse extends ActionResponse implements StatusToXContent {
|
||||||
|
|
||||||
private InternalSearchResponse internalResponse;
|
private InternalSearchResponse internalResponse;
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ package org.elasticsearch.action.search.type;
|
|||||||
|
|
||||||
import com.carrotsearch.hppc.IntArrayList;
|
import com.carrotsearch.hppc.IntArrayList;
|
||||||
import org.apache.lucene.search.ScoreDoc;
|
import org.apache.lucene.search.ScoreDoc;
|
||||||
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.ExceptionsHelper;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.search.*;
|
import org.elasticsearch.action.search.*;
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
@ -31,6 +33,7 @@ import org.elasticsearch.common.component.AbstractComponent;
|
|||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.util.concurrent.AtomicArray;
|
import org.elasticsearch.common.util.concurrent.AtomicArray;
|
||||||
|
import org.elasticsearch.search.SearchContextMissingException;
|
||||||
import org.elasticsearch.search.action.SearchServiceListener;
|
import org.elasticsearch.search.action.SearchServiceListener;
|
||||||
import org.elasticsearch.search.action.SearchServiceTransportAction;
|
import org.elasticsearch.search.action.SearchServiceTransportAction;
|
||||||
import org.elasticsearch.search.controller.SearchPhaseController;
|
import org.elasticsearch.search.controller.SearchPhaseController;
|
||||||
@ -171,8 +174,13 @@ public class TransportSearchScrollQueryThenFetchAction extends AbstractComponent
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void onFailure(Throwable t) {
|
||||||
|
Throwable cause = ExceptionsHelper.unwrapCause(t);
|
||||||
|
if (cause instanceof SearchContextMissingException) {
|
||||||
|
listener.onFailure(t);
|
||||||
|
} else {
|
||||||
onQueryPhaseFailure(shardIndex, counter, searchId, t);
|
onQueryPhaseFailure(shardIndex, counter, searchId, t);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.common.xcontent;
|
||||||
|
|
||||||
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface StatusToXContent extends ToXContent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the REST status to make sure it is returned correctly
|
||||||
|
*/
|
||||||
|
RestStatus status();
|
||||||
|
}
|
@ -33,6 +33,7 @@ import org.elasticsearch.rest.BaseRestHandler;
|
|||||||
import org.elasticsearch.rest.RestChannel;
|
import org.elasticsearch.rest.RestChannel;
|
||||||
import org.elasticsearch.rest.RestController;
|
import org.elasticsearch.rest.RestController;
|
||||||
import org.elasticsearch.rest.RestRequest;
|
import org.elasticsearch.rest.RestRequest;
|
||||||
|
import org.elasticsearch.rest.action.support.RestStatusToXContentListener;
|
||||||
import org.elasticsearch.rest.action.support.RestToXContentListener;
|
import org.elasticsearch.rest.action.support.RestToXContentListener;
|
||||||
import org.elasticsearch.search.Scroll;
|
import org.elasticsearch.search.Scroll;
|
||||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||||
@ -71,7 +72,7 @@ public class RestSearchAction extends BaseRestHandler {
|
|||||||
SearchRequest searchRequest;
|
SearchRequest searchRequest;
|
||||||
searchRequest = RestSearchAction.parseSearchRequest(request);
|
searchRequest = RestSearchAction.parseSearchRequest(request);
|
||||||
searchRequest.listenerThreaded(false);
|
searchRequest.listenerThreaded(false);
|
||||||
client.search(searchRequest, new RestToXContentListener<SearchResponse>(channel));
|
client.search(searchRequest, new RestStatusToXContentListener<SearchResponse>(channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SearchRequest parseSearchRequest(RestRequest request) {
|
public static SearchRequest parseSearchRequest(RestRequest request) {
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.elasticsearch.rest.action.search;
|
package org.elasticsearch.rest.action.search;
|
||||||
|
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
|
||||||
import org.elasticsearch.action.search.SearchScrollRequest;
|
import org.elasticsearch.action.search.SearchScrollRequest;
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
@ -29,7 +28,7 @@ import org.elasticsearch.rest.RestChannel;
|
|||||||
import org.elasticsearch.rest.RestController;
|
import org.elasticsearch.rest.RestController;
|
||||||
import org.elasticsearch.rest.RestRequest;
|
import org.elasticsearch.rest.RestRequest;
|
||||||
import org.elasticsearch.rest.action.support.RestActions;
|
import org.elasticsearch.rest.action.support.RestActions;
|
||||||
import org.elasticsearch.rest.action.support.RestToXContentListener;
|
import org.elasticsearch.rest.action.support.RestStatusToXContentListener;
|
||||||
import org.elasticsearch.search.Scroll;
|
import org.elasticsearch.search.Scroll;
|
||||||
|
|
||||||
import static org.elasticsearch.common.unit.TimeValue.parseTimeValue;
|
import static org.elasticsearch.common.unit.TimeValue.parseTimeValue;
|
||||||
@ -63,6 +62,7 @@ public class RestSearchScrollAction extends BaseRestHandler {
|
|||||||
if (scroll != null) {
|
if (scroll != null) {
|
||||||
searchScrollRequest.scroll(new Scroll(parseTimeValue(scroll, null)));
|
searchScrollRequest.scroll(new Scroll(parseTimeValue(scroll, null)));
|
||||||
}
|
}
|
||||||
client.searchScroll(searchScrollRequest, new RestToXContentListener<SearchResponse>(channel));
|
|
||||||
|
client.searchScroll(searchScrollRequest, new RestStatusToXContentListener(channel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.rest.action.support;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.xcontent.StatusToXContent;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.rest.BytesRestResponse;
|
||||||
|
import org.elasticsearch.rest.RestChannel;
|
||||||
|
import org.elasticsearch.rest.RestResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class RestStatusToXContentListener<Response extends StatusToXContent> extends RestResponseListener<Response> {
|
||||||
|
|
||||||
|
public RestStatusToXContentListener(RestChannel channel) {
|
||||||
|
super(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final RestResponse buildResponse(Response response) throws Exception {
|
||||||
|
return buildResponse(response, channel.newBuilder());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final RestResponse buildResponse(Response response, XContentBuilder builder) throws Exception {
|
||||||
|
builder.startObject();
|
||||||
|
response.toXContent(builder, channel.request());
|
||||||
|
builder.endObject();
|
||||||
|
return new BytesRestResponse(response.status(), builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,6 +20,7 @@
|
|||||||
package org.elasticsearch.search;
|
package org.elasticsearch.search;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -36,4 +37,9 @@ public class SearchContextMissingException extends ElasticsearchException {
|
|||||||
public long id() {
|
public long id() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RestStatus status() {
|
||||||
|
return RestStatus.NOT_FOUND;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.elasticsearch.search.scroll;
|
package org.elasticsearch.search.scroll;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||||
import org.elasticsearch.action.search.ClearScrollResponse;
|
import org.elasticsearch.action.search.ClearScrollResponse;
|
||||||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||||
@ -29,6 +30,8 @@ import org.elasticsearch.common.settings.ImmutableSettings;
|
|||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException;
|
import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException;
|
||||||
import org.elasticsearch.index.query.QueryBuilders;
|
import org.elasticsearch.index.query.QueryBuilders;
|
||||||
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
import org.elasticsearch.search.SearchContextMissingException;
|
||||||
import org.elasticsearch.search.SearchHit;
|
import org.elasticsearch.search.SearchHit;
|
||||||
import org.elasticsearch.search.sort.SortOrder;
|
import org.elasticsearch.search.sort.SortOrder;
|
||||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||||
@ -39,6 +42,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||||
|
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -287,19 +291,8 @@ public class SearchScrollTests extends ElasticsearchIntegrationTest {
|
|||||||
.execute().actionGet();
|
.execute().actionGet();
|
||||||
assertThat(clearResponse.isSucceeded(), equalTo(true));
|
assertThat(clearResponse.isSucceeded(), equalTo(true));
|
||||||
|
|
||||||
searchResponse1 = client().prepareSearchScroll(searchResponse1.getScrollId())
|
assertThrows(client().prepareSearchScroll(searchResponse1.getScrollId()).setScroll(TimeValue.timeValueMinutes(2)), SearchContextMissingException.class);
|
||||||
.setScroll(TimeValue.timeValueMinutes(2))
|
assertThrows(client().prepareSearchScroll(searchResponse2.getScrollId()).setScroll(TimeValue.timeValueMinutes(2)), SearchContextMissingException.class);
|
||||||
.execute().actionGet();
|
|
||||||
|
|
||||||
searchResponse2 = client().prepareSearchScroll(searchResponse2.getScrollId())
|
|
||||||
.setScroll(TimeValue.timeValueMinutes(2))
|
|
||||||
.execute().actionGet();
|
|
||||||
|
|
||||||
assertThat(searchResponse1.getHits().getTotalHits(), equalTo(0l));
|
|
||||||
assertThat(searchResponse1.getHits().hits().length, equalTo(0));
|
|
||||||
|
|
||||||
assertThat(searchResponse2.getHits().getTotalHits(), equalTo(0l));
|
|
||||||
assertThat(searchResponse2.getHits().hits().length, equalTo(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -404,19 +397,8 @@ public class SearchScrollTests extends ElasticsearchIntegrationTest {
|
|||||||
.execute().actionGet();
|
.execute().actionGet();
|
||||||
assertThat(clearResponse.isSucceeded(), equalTo(true));
|
assertThat(clearResponse.isSucceeded(), equalTo(true));
|
||||||
|
|
||||||
searchResponse1 = client().prepareSearchScroll(searchResponse1.getScrollId())
|
assertThrows(cluster().transportClient().prepareSearchScroll(searchResponse1.getScrollId()).setScroll(TimeValue.timeValueMinutes(2)), SearchContextMissingException.class);
|
||||||
.setScroll(TimeValue.timeValueMinutes(2))
|
assertThrows(cluster().transportClient().prepareSearchScroll(searchResponse2.getScrollId()).setScroll(TimeValue.timeValueMinutes(2)), SearchContextMissingException.class);
|
||||||
.execute().actionGet();
|
|
||||||
|
|
||||||
searchResponse2 = client().prepareSearchScroll(searchResponse2.getScrollId())
|
|
||||||
.setScroll(TimeValue.timeValueMinutes(2))
|
|
||||||
.execute().actionGet();
|
|
||||||
|
|
||||||
assertThat(searchResponse1.getHits().getTotalHits(), equalTo(0l));
|
|
||||||
assertThat(searchResponse1.getHits().hits().length, equalTo(0));
|
|
||||||
|
|
||||||
assertThat(searchResponse2.getHits().getTotalHits(), equalTo(0l));
|
|
||||||
assertThat(searchResponse2.getHits().hits().length, equalTo(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -447,7 +429,24 @@ public class SearchScrollTests extends ElasticsearchIntegrationTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThatNonExistingScrollIdReturnsCorrectException() throws Exception {
|
||||||
|
client().prepareIndex("index", "type", "1").setSource("field", "value").execute().get();
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
try {
|
||||||
|
SearchResponse searchResponse = client().prepareSearch("index").setSize(1).setScroll("1m").get();
|
||||||
|
assertThat(searchResponse.getScrollId(), is(notNullValue()));
|
||||||
|
|
||||||
|
ClearScrollResponse clearScrollResponse = client().prepareClearScroll().addScrollId(searchResponse.getScrollId()).get();
|
||||||
|
assertThat(clearScrollResponse.isSucceeded(), is(true));
|
||||||
|
|
||||||
|
cluster().transportClient().prepareSearchScroll(searchResponse.getScrollId()).get();
|
||||||
|
fail("Expected exception to happen due to non-existing scroll id");
|
||||||
|
} catch (ElasticsearchException e) {
|
||||||
|
assertThat(e.status(), is(RestStatus.NOT_FOUND));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user