34
34
35
35
import com .carrotsearch .randomizedtesting .annotations .ParametersFactory ;
36
36
37
+ import org .opensearch .action .admin .cluster .settings .ClusterUpdateSettingsRequest ;
37
38
import org .opensearch .action .admin .indices .alias .Alias ;
38
39
import org .opensearch .action .admin .indices .forcemerge .ForceMergeResponse ;
39
40
import org .opensearch .action .search .SearchResponse ;
42
43
import org .opensearch .cluster .metadata .IndexMetadata ;
43
44
import org .opensearch .common .settings .Settings ;
44
45
import org .opensearch .common .time .DateFormatter ;
46
+ import org .opensearch .common .unit .TimeValue ;
45
47
import org .opensearch .common .util .FeatureFlags ;
46
48
import org .opensearch .index .cache .request .RequestCacheStats ;
47
49
import org .opensearch .index .query .QueryBuilders ;
48
50
import org .opensearch .search .aggregations .bucket .global .GlobalAggregationBuilder ;
49
51
import org .opensearch .search .aggregations .bucket .histogram .DateHistogramInterval ;
50
52
import org .opensearch .search .aggregations .bucket .histogram .Histogram ;
51
53
import org .opensearch .search .aggregations .bucket .histogram .Histogram .Bucket ;
54
+ import org .opensearch .test .OpenSearchIntegTestCase ;
52
55
import org .opensearch .test .ParameterizedStaticSettingsOpenSearchIntegTestCase ;
53
56
import org .opensearch .test .hamcrest .OpenSearchAssertions ;
54
57
58
+ import java .time .Duration ;
59
+ import java .time .Instant ;
55
60
import java .time .ZoneId ;
56
61
import java .time .ZoneOffset ;
57
62
import java .time .ZonedDateTime ;
60
65
import java .util .Collection ;
61
66
import java .util .List ;
62
67
68
+ import static org .opensearch .cluster .metadata .IndexMetadata .SETTING_NUMBER_OF_REPLICAS ;
69
+ import static org .opensearch .cluster .metadata .IndexMetadata .SETTING_NUMBER_OF_SHARDS ;
70
+ import static org .opensearch .indices .IndicesRequestCache .INDICES_REQUEST_CACHE_STALENESS_THRESHOLD_SETTING ;
63
71
import static org .opensearch .search .SearchService .CLUSTER_CONCURRENT_SEGMENT_SEARCH_SETTING ;
64
72
import static org .opensearch .search .aggregations .AggregationBuilders .dateHistogram ;
65
73
import static org .opensearch .search .aggregations .AggregationBuilders .dateRange ;
69
77
import static org .hamcrest .Matchers .equalTo ;
70
78
import static org .hamcrest .Matchers .greaterThan ;
71
79
80
+ @ OpenSearchIntegTestCase .ClusterScope (scope = OpenSearchIntegTestCase .Scope .TEST , numDataNodes = 0 , supportsDedicatedMasters = false )
72
81
public class IndicesRequestCacheIT extends ParameterizedStaticSettingsOpenSearchIntegTestCase {
73
82
public IndicesRequestCacheIT (Settings settings ) {
74
83
super (settings );
@@ -97,7 +106,12 @@ public void testCacheAggs() throws Exception {
97
106
.indices ()
98
107
.prepareCreate ("index" )
99
108
.setMapping ("f" , "type=date" )
100
- .setSettings (Settings .builder ().put (IndicesRequestCache .INDEX_CACHE_REQUEST_ENABLED_SETTING .getKey (), true ))
109
+ .setSettings (
110
+ Settings .builder ()
111
+ .put (IndicesRequestCache .INDEX_CACHE_REQUEST_ENABLED_SETTING .getKey (), true )
112
+ .put (SETTING_NUMBER_OF_SHARDS , 1 )
113
+ .put (SETTING_NUMBER_OF_REPLICAS , 0 )
114
+ )
101
115
.get ()
102
116
);
103
117
indexRandom (
@@ -677,14 +691,89 @@ public void testCacheWithInvalidation() throws Exception {
677
691
assertCacheState (client , "index" , 1 , 2 );
678
692
}
679
693
694
+ // when staleness threshold is high, it should NOT clean-up
695
+ public void testStaleKeysCleanup_ThresholdUpdates () throws Exception {
696
+ Instant start = Instant .now ();
697
+ long thresholdInMillis = 1_500 ;
698
+ String node = internalCluster ().startNode (
699
+ Settings .builder ()
700
+ .put (IndicesRequestCache .SETTING_INDICES_REQUEST_CACHE_STALENESS_THRESHOLD_SETTING , 0.90 )
701
+ .put (IndicesRequestCache .SETTING_INDICES_REQUEST_CACHE_CLEAN_INTERVAL_SETTING , TimeValue .timeValueMillis (thresholdInMillis ))
702
+ );
703
+ String index = "index" ;
704
+ Client client = client (node );
705
+ setupIndex (client , index );
706
+
707
+ // create first cache entry
708
+ createCacheEntry (client , index , "hello" );
709
+ assertCacheState (client , index , 0 , 1 );
710
+ long expectedFirstCachedItemEntrySize = getRequestCacheStats (client , index ).getMemorySizeInBytes ();
711
+ assertTrue (expectedFirstCachedItemEntrySize > 0 );
712
+
713
+ // create second cache entry
714
+ createCacheEntry (client , index , "there" );
715
+ assertCacheState (client , "index" , 0 , 2 );
716
+ assertEquals (expectedFirstCachedItemEntrySize * 2 , getRequestCacheStats (client , "index" ).getMemorySizeInBytes ());
717
+
718
+ // force refresh so that it creates 2 stale keys in the cache for the cache cleaner to pick up.
719
+ flushAndRefresh ("index" );
720
+ client ().prepareIndex ("index" ).setId ("1" ).setSource ("k" , "good bye" );
721
+ ensureSearchable ("index" );
722
+
723
+ // create another entry
724
+ createCacheEntry (client , index , "hello1" );
725
+ assertCacheState (client , "index" , 0 , 3 );
726
+ long cacheSizeBeforeCleanup = getRequestCacheStats (client , "index" ).getMemorySizeInBytes ();
727
+ assertTrue (cacheSizeBeforeCleanup > expectedFirstCachedItemEntrySize * 2 );
728
+ assertEquals (cacheSizeBeforeCleanup , expectedFirstCachedItemEntrySize * 3 , 2 );
729
+
730
+ Instant end = Instant .now ();
731
+ long elapsedTimeMillis = Duration .between (start , end ).toMillis ();
732
+ // if this test is flaky, increase the sleep time.
733
+ long sleepTime = (thresholdInMillis - elapsedTimeMillis ) + 2_000 ;
734
+ Thread .sleep (sleepTime );
735
+
736
+ // cache cleaner should have skipped the cleanup
737
+ long cacheSizeAfterCleanup = getRequestCacheStats (client , "index" ).getMemorySizeInBytes ();
738
+ assertEquals (cacheSizeBeforeCleanup , cacheSizeAfterCleanup );
739
+
740
+ // Set indices.requests.cache.cleanup.staleness_threshold to "10%"
741
+ ClusterUpdateSettingsRequest updateSettingsRequest = new ClusterUpdateSettingsRequest ();
742
+ updateSettingsRequest .persistentSettings (Settings .builder ().put (INDICES_REQUEST_CACHE_STALENESS_THRESHOLD_SETTING .getKey (), 0.10 ));
743
+ assertAcked (client ().admin ().cluster ().updateSettings (updateSettingsRequest ).actionGet ());
744
+
745
+ Thread .sleep (1_500 );
746
+ cacheSizeAfterCleanup = getRequestCacheStats (client , "index" ).getMemorySizeInBytes ();
747
+ assertTrue (cacheSizeBeforeCleanup > cacheSizeAfterCleanup );
748
+ }
749
+
750
+ private void setupIndex (Client client , String index ) throws Exception {
751
+ assertAcked (
752
+ client .admin ()
753
+ .indices ()
754
+ .prepareCreate (index )
755
+ .setMapping ("k" , "type=keyword" )
756
+ .setSettings (
757
+ Settings .builder ()
758
+ .put (IndicesRequestCache .INDEX_CACHE_REQUEST_ENABLED_SETTING .getKey (), true )
759
+ .put (IndexMetadata .SETTING_NUMBER_OF_SHARDS , 1 )
760
+ .put (IndexMetadata .SETTING_NUMBER_OF_REPLICAS , 0 )
761
+ )
762
+ .get ()
763
+ );
764
+ indexRandom (true , client .prepareIndex (index ).setSource ("k" , "hello" ));
765
+ indexRandom (true , client .prepareIndex (index ).setSource ("k" , "there" ));
766
+ ensureSearchable (index );
767
+ }
768
+
769
+ private void createCacheEntry (Client client , String index , String value ) {
770
+ SearchResponse resp = client .prepareSearch (index ).setRequestCache (true ).setQuery (QueryBuilders .termQuery ("k" , value )).get ();
771
+ assertSearchResponse (resp );
772
+ OpenSearchAssertions .assertAllSuccessful (resp );
773
+ }
774
+
680
775
private static void assertCacheState (Client client , String index , long expectedHits , long expectedMisses ) {
681
- RequestCacheStats requestCacheStats = client .admin ()
682
- .indices ()
683
- .prepareStats (index )
684
- .setRequestCache (true )
685
- .get ()
686
- .getTotal ()
687
- .getRequestCache ();
776
+ RequestCacheStats requestCacheStats = getRequestCacheStats (client , index );
688
777
// Check the hit count and miss count together so if they are not
689
778
// correct we can see both values
690
779
assertEquals (
@@ -694,4 +783,7 @@ private static void assertCacheState(Client client, String index, long expectedH
694
783
695
784
}
696
785
786
+ private static RequestCacheStats getRequestCacheStats (Client client , String index ) {
787
+ return client .admin ().indices ().prepareStats (index ).setRequestCache (true ).get ().getTotal ().getRequestCache ();
788
+ }
697
789
}
0 commit comments