Skip to content

Commit 0324edd

Browse files
Route search traffic to _primary_first for warm index (#14934)
Signed-off-by: Neetika Singhal <neetiks@amazon.com>
1 parent e7ee950 commit 0324edd

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

server/src/main/java/org/opensearch/cluster/routing/OperationRouting.java

+9
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242
import org.opensearch.common.settings.ClusterSettings;
4343
import org.opensearch.common.settings.Setting;
4444
import org.opensearch.common.settings.Settings;
45+
import org.opensearch.common.util.FeatureFlags;
4546
import org.opensearch.core.common.Strings;
4647
import org.opensearch.core.index.shard.ShardId;
48+
import org.opensearch.index.IndexModule;
4749
import org.opensearch.index.IndexNotFoundException;
4850
import org.opensearch.node.ResponseCollectorService;
4951

@@ -245,6 +247,13 @@ public GroupShardsIterator<ShardIterator> searchShards(
245247
preference = Preference.PRIMARY.type();
246248
}
247249

250+
if (FeatureFlags.isEnabled(FeatureFlags.TIERED_REMOTE_INDEX)
251+
&& IndexModule.DataLocalityType.PARTIAL.name()
252+
.equals(indexMetadataForShard.getSettings().get(IndexModule.INDEX_STORE_LOCALITY_SETTING.getKey()))
253+
&& (preference == null || preference.isEmpty())) {
254+
preference = Preference.PRIMARY_FIRST.type();
255+
}
256+
248257
ShardIterator iterator = preferenceActiveShardIterator(
249258
shard,
250259
clusterState.nodes().getLocalNodeId(),

server/src/test/java/org/opensearch/cluster/routing/OperationRoutingTests.java

+64
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
import org.opensearch.cluster.node.DiscoveryNodeRole;
4242
import org.opensearch.cluster.routing.allocation.decider.AwarenessAllocationDecider;
4343
import org.opensearch.cluster.service.ClusterService;
44+
import org.opensearch.common.SuppressForbidden;
4445
import org.opensearch.common.settings.ClusterSettings;
4546
import org.opensearch.common.settings.Settings;
4647
import org.opensearch.common.unit.TimeValue;
48+
import org.opensearch.common.util.FeatureFlags;
4749
import org.opensearch.common.util.io.IOUtils;
4850
import org.opensearch.core.index.Index;
4951
import org.opensearch.core.index.shard.ShardId;
@@ -1054,6 +1056,68 @@ public void testSearchableSnapshotPrimaryDefault() throws Exception {
10541056
}
10551057
}
10561058

1059+
@SuppressForbidden(reason = "feature flag overrides")
1060+
public void testPartialIndexPrimaryDefault() throws Exception {
1061+
System.setProperty(FeatureFlags.TIERED_REMOTE_INDEX, "true");
1062+
final int numIndices = 1;
1063+
final int numShards = 2;
1064+
final int numReplicas = 2;
1065+
final String[] indexNames = new String[numIndices];
1066+
for (int i = 0; i < numIndices; i++) {
1067+
indexNames[i] = "test" + i;
1068+
}
1069+
// The first index is a partial index
1070+
final String indexName = indexNames[0];
1071+
ClusterService clusterService = null;
1072+
ThreadPool threadPool = null;
1073+
1074+
try {
1075+
OperationRouting opRouting = new OperationRouting(
1076+
Settings.EMPTY,
1077+
new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)
1078+
);
1079+
1080+
ClusterState state = ClusterStateCreationUtils.stateWithAssignedPrimariesAndReplicas(indexNames, numShards, numReplicas);
1081+
threadPool = new TestThreadPool("testPartialIndexPrimaryDefault");
1082+
clusterService = ClusterServiceUtils.createClusterService(threadPool);
1083+
1084+
// Update the index config within the cluster state to modify the index to a partial index
1085+
IndexMetadata partialIndexMetadata = IndexMetadata.builder(indexName)
1086+
.settings(
1087+
Settings.builder()
1088+
.put(state.metadata().index(indexName).getSettings())
1089+
.put(IndexModule.INDEX_STORE_LOCALITY_SETTING.getKey(), IndexModule.DataLocalityType.PARTIAL)
1090+
.build()
1091+
)
1092+
.build();
1093+
Metadata.Builder metadataBuilder = Metadata.builder(state.metadata())
1094+
.put(partialIndexMetadata, false)
1095+
.generateClusterUuidIfNeeded();
1096+
state = ClusterState.builder(state).metadata(metadataBuilder.build()).build();
1097+
1098+
// Verify default preference is primary only
1099+
GroupShardsIterator<ShardIterator> groupIterator = opRouting.searchShards(state, indexNames, null, null);
1100+
assertThat("One group per index shard", groupIterator.size(), equalTo(numIndices * numShards));
1101+
1102+
for (ShardIterator shardIterator : groupIterator) {
1103+
assertTrue("Only primary should exist with no preference", shardIterator.nextOrNull().primary());
1104+
}
1105+
1106+
// Verify alternative preference can be applied to a partial index
1107+
groupIterator = opRouting.searchShards(state, indexNames, null, "_replica");
1108+
assertThat("One group per index shard", groupIterator.size(), equalTo(numIndices * numShards));
1109+
1110+
for (ShardIterator shardIterator : groupIterator) {
1111+
assertThat("Replica shards will be returned", shardIterator.size(), equalTo(numReplicas));
1112+
assertFalse("Returned shard should be a replica", shardIterator.nextOrNull().primary());
1113+
}
1114+
} finally {
1115+
IOUtils.close(clusterService);
1116+
terminate(threadPool);
1117+
System.setProperty(FeatureFlags.TIERED_REMOTE_INDEX, "false");
1118+
}
1119+
}
1120+
10571121
private DiscoveryNode[] setupNodes() {
10581122
// Sets up two data nodes in zone-a and one data node in zone-b
10591123
List<String> zones = Arrays.asList("a", "a", "b");

0 commit comments

Comments
 (0)