diff --git a/docs/changelog/94164.yaml b/docs/changelog/94164.yaml new file mode 100644 index 0000000000000..b55e09225d7a0 --- /dev/null +++ b/docs/changelog/94164.yaml @@ -0,0 +1,5 @@ +pr: 94164 +summary: Avoid NPE in Stateless Get/mGet +area: CRUD +type: bug +issues: [] diff --git a/server/src/main/java/org/elasticsearch/action/get/TransportGetAction.java b/server/src/main/java/org/elasticsearch/action/get/TransportGetAction.java index 182fdf087a8c2..c08eec6dd3cc1 100644 --- a/server/src/main/java/org/elasticsearch/action/get/TransportGetAction.java +++ b/server/src/main/java/org/elasticsearch/action/get/TransportGetAction.java @@ -13,7 +13,10 @@ import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.routing.PlainShardIterator; import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.Writeable; @@ -27,6 +30,7 @@ import org.elasticsearch.transport.TransportService; import java.io.IOException; +import java.util.stream.Collectors; /** * Performs the get operation. @@ -67,7 +71,7 @@ protected boolean resolveIndex(GetRequest request) { @Override protected ShardIterator shards(ClusterState state, InternalRequest request) { - return clusterService.operationRouting() + ShardIterator iterator = clusterService.operationRouting() .getShards( clusterService.state(), request.concreteIndex(), @@ -75,6 +79,19 @@ protected ShardIterator shards(ClusterState state, InternalRequest request) { request.request().routing(), request.request().preference() ); + if (iterator == null) { + return null; + } + // If it is stateless, only route isPromotableToPrimary shards. This is a temporary workaround until a more cohesive solution can be + // implemented for search shards. + if (DiscoveryNode.isStateless(clusterService.getSettings())) { + return new PlainShardIterator( + iterator.shardId(), + iterator.getShardRoutings().stream().filter(ShardRouting::isPromotableToPrimary).collect(Collectors.toList()) + ); + } else { + return iterator; + } } @Override diff --git a/server/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java b/server/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java index b63f4b5b332a4..a173ff4407968 100644 --- a/server/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java +++ b/server/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java @@ -15,7 +15,10 @@ import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.routing.PlainShardIterator; import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.Writeable; @@ -29,6 +32,7 @@ import org.elasticsearch.transport.TransportService; import java.io.IOException; +import java.util.stream.Collectors; import static org.elasticsearch.core.Strings.format; @@ -81,8 +85,21 @@ protected boolean resolveIndex(MultiGetShardRequest request) { @Override protected ShardIterator shards(ClusterState state, InternalRequest request) { - return clusterService.operationRouting() + ShardIterator iterator = clusterService.operationRouting() .getShards(state, request.request().index(), request.request().shardId(), request.request().preference()); + if (iterator == null) { + return null; + } + // If it is stateless, only route promotable shards. This is a temporary workaround until a more cohesive solution can be + // implemented for search shards. + if (DiscoveryNode.isStateless(clusterService.getSettings())) { + return new PlainShardIterator( + iterator.shardId(), + iterator.getShardRoutings().stream().filter(ShardRouting::isPromotableToPrimary).collect(Collectors.toList()) + ); + } else { + return iterator; + } } @Override