5353import org .slf4j .LoggerFactory ;
5454
5555import static org .awaitility .Awaitility .await ;
56- import org .junit .Ignore ;
5756
5857public class IndexStoreServiceTest {
5958
@@ -309,12 +308,14 @@ public void queryFromFileTest() throws InterruptedException, ExecutionException
309308 }
310309 }
311310
312- @ Ignore ("Flaky: fails 1/65 runs (1.5%)" )
313311 @ Test
314312 public void concurrentGetTest () throws InterruptedException {
315313 storeConfig .setTieredStoreIndexFileMaxIndexNum (2000 );
316314 indexService = new IndexStoreService (fileAllocator , filePath );
317315 indexService .start ();
316+ // Wait for service thread to complete its first iteration and enter 10s wait,
317+ // preventing compaction from racing with queries below.
318+ TimeUnit .MILLISECONDS .sleep (500 );
318319
319320 int fileCount = 10 ;
320321 for (int j = 0 ; j < fileCount ; j ++) {
@@ -354,41 +355,37 @@ public void concurrentGetTest() throws InterruptedException {
354355 Assert .assertTrue (result .get ());
355356 }
356357
357- @ Ignore ("Flaky: fails 35/100 runs (35.0%)" )
358358 @ Test
359359 public void queryCrossFileBoundaryTest () throws InterruptedException , ExecutionException {
360360 indexService = new IndexStoreService (fileAllocator , filePath );
361361 indexService .start ();
362362
363- // Create first file with early beginTime
364- long file1Begin = System .currentTimeMillis ();
365- for (int i = 0 ; i < storeConfig .getTieredStoreIndexFileMaxIndexNum () - 1 ; i ++) {
363+ long file1Begin = indexService .getTimeStoreTable ().firstKey ();
364+
365+ // Fill file1 completely to trigger SEALED and create file2.
366+ // maxIndexNum=20, seals when indexItemCount + 1 >= 20, so 20 puts will seal and overflow.
367+ for (int i = 0 ; i < storeConfig .getTieredStoreIndexFileMaxIndexNum (); i ++) {
366368 indexService .putKey (TOPIC_NAME , TOPIC_ID , QUEUE_ID ,
367369 Collections .singleton ("crossKey" ), i * 100L , MESSAGE_SIZE , file1Begin + i * 1000 );
368370 }
369371
370- // Create second file with later beginTime (beyond query range)
371- long file2Begin = System .currentTimeMillis () + 100_000 ;
372- indexService .createNewIndexFile (file2Begin );
372+ // One more put to go into file2
373+ long file2ItemTimestamp = file1Begin + 100_000 ;
373374 for (int i = 0 ; i < 5 ; i ++) {
374375 indexService .putKey (TOPIC_NAME , TOPIC_ID , QUEUE_ID ,
375- Collections .singleton ("crossKey" ), i * 100L , MESSAGE_SIZE , file2Begin + i );
376+ Collections .singleton ("crossKey" ), ( 20 + i ) * 100L , MESSAGE_SIZE , file2ItemTimestamp + i );
376377 }
377378
378379 Assert .assertEquals (2 , indexService .getTimeStoreTable ().size ());
379380
380- // Query range: beginTime is AFTER file1's beginTime but BEFORE file1's last item timestamp
381- // This should select file1, NOT file2 (file2 beginTime > queryEnd)
381+ // Query range starts AFTER file1's beginTimestamp but covers file1's items.
382+ // This verifies headMap(endTime) correctly includes file1 even though file1.key < queryBegin.
382383 long queryBegin = file1Begin + 5_000 ;
383384 long queryEnd = file1Begin + 15_000 ;
384385
385386 List <IndexItem > results = indexService .queryAsync (
386- TOPIC_NAME , "crossKey" , 10 , queryBegin , queryEnd ).get ();
387+ TOPIC_NAME , "crossKey" , 50 , queryBegin , queryEnd ).get ();
387388
388- // file1 has items at timestamps: file1Begin, file1Begin+1000, ..., file1Begin+(N-1)*1000
389- // Items in range [file1Begin+5000, file1Begin+15000] should match
390- // The bug (subMap) would return empty because file1's key < queryBegin
391389 Assert .assertFalse ("Should find index items from file covering query range" , results .isEmpty ());
392- Assert .assertTrue ("Should find items within query time range" , results .size () > 0 );
393390 }
394391}
0 commit comments