Skip to content

Commit 0ec6f63

Browse files
sgup432harshavamsi
authored andcommitted
Fix ShardNotFoundException during request cache clean up (opensearch-project#14219)
* Fix for ShardNotFoundException during request cache clean up Signed-off-by: Sagar Upadhyaya <[email protected]> * Added changelog Signed-off-by: Sagar Upadhyaya <[email protected]> * Fix forbidden gradle check Signed-off-by: Sagar Upadhyaya <[email protected]> --------- Signed-off-by: Sagar Upadhyaya <[email protected]>
1 parent 35fe96d commit 0ec6f63

File tree

4 files changed

+57
-11
lines changed

4 files changed

+57
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
7575
- Fix NPE on restore searchable snapshot ([#13911](https://github.com/opensearch-project/OpenSearch/pull/13911))
7676
- Fix double invocation of postCollection when MultiBucketCollector is present ([#14015](https://github.com/opensearch-project/OpenSearch/pull/14015))
7777
- Java high-level REST client bulk() is not respecting the bulkRequest.requireAlias(true) method call ([#14146](https://github.com/opensearch-project/OpenSearch/pull/14146))
78+
- Fix ShardNotFoundException during request cache clean up ([#14219](https://github.com/opensearch-project/OpenSearch/pull/14219))
7879

7980
### Security
8081

server/src/main/java/org/opensearch/indices/IndicesRequestCache.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ public final class IndicesRequestCache implements RemovalListener<ICacheKey<Indi
153153
private final TimeValue expire;
154154
private final ICache<Key, BytesReference> cache;
155155
private final ClusterService clusterService;
156-
private final Function<ShardId, Optional<CacheEntity>> cacheEntityLookup;
156+
// pkg-private for testing
157+
final Function<ShardId, Optional<CacheEntity>> cacheEntityLookup;
157158
// pkg-private for testing
158159
final IndicesRequestCacheCleanupManager cacheCleanupManager;
159160

server/src/main/java/org/opensearch/indices/IndicesService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ public IndicesService(
404404
if (indexService == null) {
405405
return Optional.empty();
406406
}
407-
return Optional.of(new IndexShardCacheEntity(indexService.getShard(shardId.id())));
407+
return Optional.of(new IndexShardCacheEntity(indexService.getShardOrNull(shardId.id())));
408408
}), cacheService, threadPool, clusterService);
409409
this.indicesQueryCache = new IndicesQueryCache(settings);
410410
this.mapperRegistry = mapperRegistry;

server/src/test/java/org/opensearch/indices/IndicesRequestCacheTests.java

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import java.util.concurrent.CountDownLatch;
106106
import java.util.concurrent.ExecutorService;
107107
import java.util.concurrent.Executors;
108+
import java.util.concurrent.TimeUnit;
108109
import java.util.concurrent.atomic.AtomicInteger;
109110

110111
import static java.util.Collections.emptyMap;
@@ -798,15 +799,9 @@ private DirectoryReader getReader(IndexWriter writer, ShardId shardId) throws IO
798799

799800
private IndicesRequestCache getIndicesRequestCache(Settings settings) {
800801
IndicesService indicesService = getInstanceFromNode(IndicesService.class);
801-
return new IndicesRequestCache(settings, (shardId -> {
802-
IndexService indexService = null;
803-
try {
804-
indexService = indicesService.indexServiceSafe(shardId.getIndex());
805-
} catch (IndexNotFoundException ex) {
806-
return Optional.empty();
807-
}
808-
return Optional.of(new IndicesService.IndexShardCacheEntity(indexService.getShard(shardId.id())));
809-
}),
802+
return new IndicesRequestCache(
803+
settings,
804+
indicesService.indicesRequestCache.cacheEntityLookup,
810805
new CacheModule(new ArrayList<>(), Settings.EMPTY).getCacheService(),
811806
threadPool,
812807
ClusterServiceUtils.createClusterService(threadPool)
@@ -1419,6 +1414,55 @@ public void testDeleteAndCreateIndexShardOnSameNodeAndVerifyStats() throws Excep
14191414
IOUtils.close(reader, writer, dir, cache);
14201415
}
14211416

1417+
public void testIndexShardClosedAndVerifyCacheCleanUpWorksSuccessfully() throws Exception {
1418+
threadPool = getThreadPool();
1419+
String indexName = "test1";
1420+
// Create a shard
1421+
IndexService indexService = createIndex(
1422+
indexName,
1423+
Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1).put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0).build()
1424+
);
1425+
IndexShard indexShard = indexService.getShard(0);
1426+
Directory dir = newDirectory();
1427+
IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig());
1428+
writer.addDocument(newDoc(0, "foo"));
1429+
writer.addDocument(newDoc(1, "hack"));
1430+
DirectoryReader reader = OpenSearchDirectoryReader.wrap(DirectoryReader.open(writer), indexShard.shardId());
1431+
Loader loader = new Loader(reader, 0);
1432+
1433+
// Set clean interval to a high value as we will do it manually here.
1434+
IndicesRequestCache cache = getIndicesRequestCache(
1435+
Settings.builder()
1436+
.put(IndicesRequestCache.INDICES_REQUEST_CACHE_CLEANUP_INTERVAL_SETTING_KEY, TimeValue.timeValueMillis(100000))
1437+
.build()
1438+
);
1439+
IndicesService.IndexShardCacheEntity cacheEntity = new IndicesService.IndexShardCacheEntity(indexShard);
1440+
TermQueryBuilder termQuery = new TermQueryBuilder("id", "bar");
1441+
1442+
// Cache some values for indexShard
1443+
BytesReference value = cache.getOrCompute(cacheEntity, loader, reader, getTermBytes());
1444+
1445+
// Verify response and stats.
1446+
assertEquals("foo", value.streamInput().readString());
1447+
RequestCacheStats stats = indexShard.requestCache().stats();
1448+
assertEquals("foo", value.streamInput().readString());
1449+
assertEquals(1, cache.count());
1450+
assertEquals(1, stats.getMissCount());
1451+
assertTrue(stats.getMemorySizeInBytes() > 0);
1452+
1453+
// Remove the shard making its cache entries stale
1454+
IOUtils.close(reader, writer, dir);
1455+
indexService.removeShard(0, "force");
1456+
1457+
assertBusy(() -> { assertEquals(IndexShardState.CLOSED, indexShard.state()); }, 1, TimeUnit.SECONDS);
1458+
1459+
// Trigger clean up of cache. Should not throw any exception.
1460+
cache.cacheCleanupManager.cleanCache();
1461+
// Verify all cleared up.
1462+
assertEquals(0, cache.count());
1463+
IOUtils.close(cache);
1464+
}
1465+
14221466
public static String generateString(int length) {
14231467
String characters = "abcdefghijklmnopqrstuvwxyz";
14241468
StringBuilder sb = new StringBuilder(length);

0 commit comments

Comments
 (0)