Skip to content

Commit

Permalink
Made single shards APIs fail if routing is configured to be required …
Browse files Browse the repository at this point in the history
…in the mapping.

 This change make single shard requests fail when no routing is specified and routing has been configured to be required in the mapping. Thi

 Closes elastic#4506
  • Loading branch information
martijnvg authored and brusic committed Jan 19, 2014
1 parent d2c3f64 commit 0bd6c7f
Show file tree
Hide file tree
Showing 18 changed files with 248 additions and 20 deletions.
2 changes: 1 addition & 1 deletion rest-api-spec/test/create/50_parent.yaml
Expand Up @@ -41,7 +41,7 @@
- match: { fields._routing: "5"}

- do:
catch: missing
catch: param
get:
index: test_1
type: test
Expand Down
1 change: 1 addition & 0 deletions rest-api-spec/test/exists/30_parent.yaml
Expand Up @@ -33,6 +33,7 @@
- is_true: ''

- do:
catch: param
exists:
index: test_1
type: test
Expand Down
2 changes: 1 addition & 1 deletion rest-api-spec/test/get/30_parent.yaml
Expand Up @@ -33,7 +33,7 @@
- match: { fields._routing: 中文}

- do:
catch: missing
catch: param
get:
index: test_1
type: test
Expand Down
2 changes: 1 addition & 1 deletion rest-api-spec/test/get_source/30_parent.yaml
Expand Up @@ -32,7 +32,7 @@
- match: { '': {foo: bar}}

- do:
catch: missing
catch: param
get_source:
index: test_1
type: test
Expand Down
2 changes: 1 addition & 1 deletion rest-api-spec/test/index/50_parent.yaml
Expand Up @@ -41,7 +41,7 @@
- match: { fields._routing: "5"}

- do:
catch: missing
catch: param
get:
index: test_1
type: test
Expand Down
2 changes: 1 addition & 1 deletion rest-api-spec/test/update/50_parent.yaml
Expand Up @@ -44,7 +44,7 @@
- match: { fields._routing: "5"}

- do:
catch: missing
catch: param
update:
index: test_1
type: test
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.elasticsearch.action;

import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.rest.RestStatus;

/**
*
Expand Down Expand Up @@ -50,4 +51,9 @@ public String type() {
public String id() {
return id;
}

@Override
public RestStatus status() {
return RestStatus.BAD_REQUEST;
}
}
Expand Up @@ -23,6 +23,7 @@
import org.apache.lucene.search.Explanation;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.support.single.shard.TransportShardSingleOperationAction;
import org.elasticsearch.cache.recycler.CacheRecycler;
import org.elasticsearch.cluster.ClusterService;
Expand Down Expand Up @@ -91,6 +92,11 @@ protected void resolveRequest(ClusterState state, ExplainRequest request) {
String concreteIndex = state.metaData().concreteIndex(request.index());
request.filteringAlias(state.metaData().filteringAliases(concreteIndex, request.index()));
request.index(state.metaData().concreteIndex(request.index()));

// Fail fast on the node that received the request.
if (request.routing() == null && state.getMetaData().routingRequired(request.index(), request.type())) {
throw new RoutingMissingException(request.index(), request.type(), request.id());
}
}

protected ExplainResponse shardOperation(ExplainRequest request, int shardId) throws ElasticSearchException {
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.elasticsearch.action.get;

import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.support.single.shard.TransportShardSingleOperationAction;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
Expand Down Expand Up @@ -89,6 +90,11 @@ protected void resolveRequest(ClusterState state, GetRequest request) {
// update the routing (request#index here is possibly an alias)
request.routing(state.metaData().resolveIndexRouting(request.routing(), request.index()));
request.index(state.metaData().concreteIndex(request.index()));

// Fail fast on the node that received the request.
if (request.routing() == null && state.getMetaData().routingRequired(request.index(), request.type())) {
throw new RoutingMissingException(request.index(), request.type(), request.id());
}
}

@Override
Expand Down
Expand Up @@ -68,6 +68,10 @@ protected void doExecute(final MultiGetRequest request, final ActionListener<Mul
responses.set(i, new MultiGetItemResponse(null, new MultiGetResponse.Failure(item.index(), item.type(), item.id(), "[" + item.index() + "] missing")));
continue;
}
if (item.routing() == null && clusterState.getMetaData().routingRequired(item.index(), item.type())) {
responses.set(i, new MultiGetItemResponse(null, new MultiGetResponse.Failure(item.index(), item.type(), item.id(), "routing is required, but hasn't been specified")));
continue;
}

item.routing(clusterState.metaData().resolveIndexRouting(item.routing(), item.index()));
item.index(clusterState.metaData().concreteIndex(item.index()));
Expand Down
Expand Up @@ -89,6 +89,14 @@ public EnumSet<Flag> getFlags() {
return flagsEnum;
}

/**
* Sets the type of document to get the term vector for.
*/
public TermVectorRequest type(String type) {
this.type = type;
return this;
}

/**
* Returns the type of document to get the term vector for.
*/
Expand All @@ -106,8 +114,9 @@ public String id() {
/**
* Sets the id of document the term vector is requested for.
*/
public void id(String id) {
public TermVectorRequest id(String id) {
this.id = id;
return this;
}

/**
Expand All @@ -117,8 +126,9 @@ public String routing() {
return routing;
}

public void routing(String routing) {
public TermVectorRequest routing(String routing) {
this.routing = routing;
return this;
}

/**
Expand Down
Expand Up @@ -71,6 +71,11 @@ protected void doExecute(final MultiTermVectorsRequest request, final ActionList
termVectorRequest.type(), termVectorRequest.id(), "[" + termVectorRequest.index() + "] missing")));
continue;
}
if (termVectorRequest.routing() == null && clusterState.getMetaData().routingRequired(termVectorRequest.index(), termVectorRequest.type())) {
responses.set(i, new MultiTermVectorsItemResponse(null, new MultiTermVectorsResponse.Failure(termVectorRequest.index(),
termVectorRequest.type(), termVectorRequest.id(), "routing is required, but hasn't been specified")));
continue;
}
termVectorRequest.index(clusterState.metaData().concreteIndex(termVectorRequest.index()));
ShardId shardId = clusterService
.operationRouting()
Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.elasticsearch.action.termvector;

import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.support.single.shard.TransportShardSingleOperationAction;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
Expand Down Expand Up @@ -80,6 +81,11 @@ protected void resolveRequest(ClusterState state, TermVectorRequest request) {
// update the routing (request#index here is possibly an alias)
request.routing(state.metaData().resolveIndexRouting(request.routing(), request.index()));
request.index(state.metaData().concreteIndex(request.index()));

// Fail fast on the node that received the request.
if (request.routing() == null && state.getMetaData().routingRequired(request.index(), request.type())) {
throw new RoutingMissingException(request.index(), request.type(), request.id());
}
}

@Override
Expand Down
Expand Up @@ -24,6 +24,7 @@
import org.elasticsearch.ElasticSearchIllegalStateException;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
Expand Down Expand Up @@ -121,6 +122,11 @@ protected boolean resolveRequest(ClusterState state, UpdateRequest request, Acti
String aliasOrIndex = request.index();
request.routing((metaData.resolveIndexRouting(request.routing(), aliasOrIndex)));
request.index(metaData.concreteIndex(request.index()));

// Fail fast on the node that received the request, rather than failing when translating on the index or delete request.
if (request.routing() == null && state.getMetaData().routingRequired(request.index(), request.type())) {
throw new RoutingMissingException(request.index(), request.type(), request.id());
}
return true;
}

Expand Down
16 changes: 16 additions & 0 deletions src/main/java/org/elasticsearch/cluster/metadata/MetaData.java
Expand Up @@ -931,6 +931,22 @@ public boolean isPatternMatchingAllIndices(String[] indicesOrAliases, String[] c
return false;
}

/**
* @param concreteIndex The concrete index to check if routing is required
* @param type The type to check if routing is required
* @return Whether routing is required according to the mapping for the specified index and type
*/
public boolean routingRequired(String concreteIndex, String type) {
IndexMetaData indexMetaData = indices.get(concreteIndex);
if (indexMetaData != null) {
MappingMetaData mappingMetaData = indexMetaData.getMappings().get(type);
if (mappingMetaData != null) {
return mappingMetaData.routing().required();
}
}
return false;
}

@Override
public UnmodifiableIterator<IndexMetaData> iterator() {
return indices.valuesIt();
Expand Down
5 changes: 3 additions & 2 deletions src/test/java/org/elasticsearch/mget/SimpleMgetTests.java
Expand Up @@ -93,8 +93,9 @@ public void testThatParentPerDocumentIsSupported() throws Exception {
assertThat(mgetResponse.getResponses()[0].isFailed(), is(false));
assertThat(mgetResponse.getResponses()[0].getResponse().isExists(), is(true));

assertThat(mgetResponse.getResponses()[1].isFailed(), is(false));
assertThat(mgetResponse.getResponses()[1].getResponse().isExists(), is(false));
assertThat(mgetResponse.getResponses()[1].isFailed(), is(true));
assertThat(mgetResponse.getResponses()[1].getResponse(), nullValue());
assertThat(mgetResponse.getResponses()[1].getFailure().getMessage(), equalTo("routing is required, but hasn't been specified"));
}

@SuppressWarnings("unchecked")
Expand Down
14 changes: 12 additions & 2 deletions src/test/java/org/elasticsearch/routing/AliasRoutingTests.java
Expand Up @@ -355,7 +355,12 @@ public void testRequiredRoutingMappingWithAlias() throws Exception {
logger.info("--> deleting with no routing, should broadcast the delete since _routing is required");
client().prepareDelete("test", "type1", "1").setRefresh(true).execute().actionGet();
for (int i = 0; i < 5; i++) {
assertThat(client().prepareGet("test", "type1", "1").execute().actionGet().isExists(), equalTo(false));
try {
client().prepareGet("test", "type1", "1").get();
assert false;
} catch (RoutingMissingException e) {
assertThat(e.getMessage(), equalTo("routing is required for [test]/[type1]/[1]"));
}
assertThat(client().prepareGet("test", "type1", "1").setRouting("0").execute().actionGet().isExists(), equalTo(false));
}

Expand All @@ -367,7 +372,12 @@ public void testRequiredRoutingMappingWithAlias() throws Exception {
client().prepareBulk().add(Requests.deleteRequest("test").type("type1").id("1")).execute().actionGet();
client().admin().indices().prepareRefresh().execute().actionGet();
for (int i = 0; i < 5; i++) {
assertThat(client().prepareGet("test", "type1", "1").execute().actionGet().isExists(), equalTo(false));
try {
assertThat(client().prepareGet("test", "type1", "1").execute().actionGet().isExists(), equalTo(false));
assert false;
} catch (RoutingMissingException e) {
assertThat(e.getMessage(), equalTo("routing is required for [test]/[type1]/[1]"));
}
assertThat(client().prepareGet("test", "type1", "1").setRouting("0").execute().actionGet().isExists(), equalTo(false));
}
}
Expand Down

0 comments on commit 0bd6c7f

Please sign in to comment.