@@ -97,10 +97,13 @@ func TestLoader_GetIndex_ShouldCacheError(t *testing.T) {
97
97
require .NoError (t , services .StopAndAwaitTerminated (ctx , loader ))
98
98
})
99
99
100
+ // Write a corrupted index.
101
+ require .NoError (t , bkt .Upload (ctx , path .Join ("user-1" , IndexCompressedFilename ), strings .NewReader ("invalid!}" )))
102
+
100
103
// Request the index multiple times.
101
104
for i := 0 ; i < 10 ; i ++ {
102
105
_ , err := loader .GetIndex (ctx , "user-1" )
103
- require .Equal (t , ErrIndexNotFound , err )
106
+ require .Equal (t , ErrIndexCorrupted , err )
104
107
}
105
108
106
109
// Ensure metrics have been updated accordingly.
@@ -121,6 +124,42 @@ func TestLoader_GetIndex_ShouldCacheError(t *testing.T) {
121
124
))
122
125
}
123
126
127
+ func TestLoader_GetIndex_ShouldCacheIndexNotFoundError (t * testing.T ) {
128
+ ctx := context .Background ()
129
+ reg := prometheus .NewPedanticRegistry ()
130
+ bkt , _ := cortex_testutil .PrepareFilesystemBucket (t )
131
+
132
+ // Create the loader.
133
+ loader := NewLoader (prepareLoaderConfig (), bkt , log .NewNopLogger (), reg )
134
+ require .NoError (t , services .StartAndAwaitRunning (ctx , loader ))
135
+ t .Cleanup (func () {
136
+ require .NoError (t , services .StopAndAwaitTerminated (ctx , loader ))
137
+ })
138
+
139
+ // Request the index multiple times.
140
+ for i := 0 ; i < 10 ; i ++ {
141
+ _ , err := loader .GetIndex (ctx , "user-1" )
142
+ require .Equal (t , ErrIndexNotFound , err )
143
+ }
144
+
145
+ // Ensure metrics have been updated accordingly.
146
+ assert .NoError (t , testutil .GatherAndCompare (reg , bytes .NewBufferString (`
147
+ # HELP cortex_bucket_index_load_failures_total Total number of bucket index loading failures.
148
+ # TYPE cortex_bucket_index_load_failures_total counter
149
+ cortex_bucket_index_load_failures_total 0
150
+ # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory.
151
+ # TYPE cortex_bucket_index_loaded gauge
152
+ cortex_bucket_index_loaded 0
153
+ # HELP cortex_bucket_index_loads_total Total number of bucket index loading attempts.
154
+ # TYPE cortex_bucket_index_loads_total counter
155
+ cortex_bucket_index_loads_total 1
156
+ ` ),
157
+ "cortex_bucket_index_loads_total" ,
158
+ "cortex_bucket_index_load_failures_total" ,
159
+ "cortex_bucket_index_loaded" ,
160
+ ))
161
+ }
162
+
124
163
func TestLoader_ShouldUpdateIndexInBackgroundOnPreviousLoadSuccess (t * testing.T ) {
125
164
ctx := context .Background ()
126
165
reg := prometheus .NewPedanticRegistry ()
@@ -191,6 +230,9 @@ func TestLoader_ShouldUpdateIndexInBackgroundOnPreviousLoadFailure(t *testing.T)
191
230
reg := prometheus .NewPedanticRegistry ()
192
231
bkt , _ := cortex_testutil .PrepareFilesystemBucket (t )
193
232
233
+ // Write a corrupted index.
234
+ require .NoError (t , bkt .Upload (ctx , path .Join ("user-1" , IndexCompressedFilename ), strings .NewReader ("invalid!}" )))
235
+
194
236
// Create the loader.
195
237
cfg := LoaderConfig {
196
238
CheckInterval : time .Second ,
@@ -205,6 +247,59 @@ func TestLoader_ShouldUpdateIndexInBackgroundOnPreviousLoadFailure(t *testing.T)
205
247
require .NoError (t , services .StopAndAwaitTerminated (ctx , loader ))
206
248
})
207
249
250
+ _ , err := loader .GetIndex (ctx , "user-1" )
251
+ assert .Equal (t , ErrIndexCorrupted , err )
252
+
253
+ // Upload the bucket index.
254
+ idx := & Index {
255
+ Version : IndexVersion1 ,
256
+ Blocks : Blocks {
257
+ {ID : ulid .MustNew (1 , nil ), MinTime : 10 , MaxTime : 20 },
258
+ },
259
+ BlockDeletionMarks : nil ,
260
+ UpdatedAt : time .Now ().Unix (),
261
+ }
262
+ require .NoError (t , WriteIndex (ctx , bkt , "user-1" , idx ))
263
+
264
+ // Wait until the index has been updated in background.
265
+ test .Poll (t , 3 * time .Second , nil , func () interface {} {
266
+ _ , err := loader .GetIndex (ctx , "user-1" )
267
+ return err
268
+ })
269
+
270
+ actualIdx , err := loader .GetIndex (ctx , "user-1" )
271
+ require .NoError (t , err )
272
+ assert .Equal (t , idx , actualIdx )
273
+
274
+ // Ensure metrics have been updated accordingly.
275
+ assert .NoError (t , testutil .GatherAndCompare (reg , bytes .NewBufferString (`
276
+ # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory.
277
+ # TYPE cortex_bucket_index_loaded gauge
278
+ cortex_bucket_index_loaded 1
279
+ ` ),
280
+ "cortex_bucket_index_loaded" ,
281
+ ))
282
+ }
283
+
284
+ func TestLoader_ShouldUpdateIndexInBackgroundOnPreviousIndexNotFound (t * testing.T ) {
285
+ ctx := context .Background ()
286
+ reg := prometheus .NewPedanticRegistry ()
287
+ bkt , _ := cortex_testutil .PrepareFilesystemBucket (t )
288
+
289
+ // Create the loader.
290
+ cfg := LoaderConfig {
291
+ CheckInterval : time .Second ,
292
+ UpdateOnStaleInterval : time .Second ,
293
+ UpdateOnErrorInterval : time .Hour , // Intentionally high to not hit it.
294
+ IdleTimeout : time .Hour , // Intentionally high to not hit it.
295
+ }
296
+
297
+ loader := NewLoader (cfg , bkt , log .NewNopLogger (), reg )
298
+ require .NoError (t , services .StartAndAwaitRunning (ctx , loader ))
299
+ t .Cleanup (func () {
300
+ require .NoError (t , services .StopAndAwaitTerminated (ctx , loader ))
301
+ })
302
+
208
303
_ , err := loader .GetIndex (ctx , "user-1" )
209
304
assert .Equal (t , ErrIndexNotFound , err )
210
305
@@ -239,7 +334,7 @@ func TestLoader_ShouldUpdateIndexInBackgroundOnPreviousLoadFailure(t *testing.T)
239
334
))
240
335
}
241
336
242
- func TestLoader_ShouldNotCacheErrorOnBackgroundUpdates (t * testing.T ) {
337
+ func TestLoader_ShouldNotCacheCriticalErrorOnBackgroundUpdates (t * testing.T ) {
243
338
ctx := context .Background ()
244
339
reg := prometheus .NewPedanticRegistry ()
245
340
bkt , _ := cortex_testutil .PrepareFilesystemBucket (t )
@@ -295,6 +390,66 @@ func TestLoader_ShouldNotCacheErrorOnBackgroundUpdates(t *testing.T) {
295
390
))
296
391
}
297
392
393
+ func TestLoader_ShouldCacheIndexNotFoundOnBackgroundUpdates (t * testing.T ) {
394
+ ctx := context .Background ()
395
+ reg := prometheus .NewPedanticRegistry ()
396
+ bkt , _ := cortex_testutil .PrepareFilesystemBucket (t )
397
+
398
+ // Create a bucket index.
399
+ idx := & Index {
400
+ Version : IndexVersion1 ,
401
+ Blocks : Blocks {
402
+ {ID : ulid .MustNew (1 , nil ), MinTime : 10 , MaxTime : 20 },
403
+ },
404
+ BlockDeletionMarks : nil ,
405
+ UpdatedAt : time .Now ().Unix (),
406
+ }
407
+ require .NoError (t , WriteIndex (ctx , bkt , "user-1" , idx ))
408
+
409
+ // Create the loader.
410
+ cfg := LoaderConfig {
411
+ CheckInterval : time .Second ,
412
+ UpdateOnStaleInterval : time .Second ,
413
+ UpdateOnErrorInterval : time .Second ,
414
+ IdleTimeout : time .Hour , // Intentionally high to not hit it.
415
+ }
416
+
417
+ loader := NewLoader (cfg , bkt , log .NewNopLogger (), reg )
418
+ require .NoError (t , services .StartAndAwaitRunning (ctx , loader ))
419
+ t .Cleanup (func () {
420
+ require .NoError (t , services .StopAndAwaitTerminated (ctx , loader ))
421
+ })
422
+
423
+ actualIdx , err := loader .GetIndex (ctx , "user-1" )
424
+ require .NoError (t , err )
425
+ assert .Equal (t , idx , actualIdx )
426
+
427
+ // Delete the bucket index.
428
+ require .NoError (t , DeleteIndex (ctx , bkt , "user-1" ))
429
+
430
+ // Wait until the next index load attempt occurs.
431
+ prevLoads := testutil .ToFloat64 (loader .loadAttempts )
432
+ test .Poll (t , 3 * time .Second , true , func () interface {} {
433
+ return testutil .ToFloat64 (loader .loadAttempts ) > prevLoads
434
+ })
435
+
436
+ // We expect the bucket index is not considered loaded because of the error.
437
+ assert .NoError (t , testutil .GatherAndCompare (reg , bytes .NewBufferString (`
438
+ # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory.
439
+ # TYPE cortex_bucket_index_loaded gauge
440
+ cortex_bucket_index_loaded 0
441
+ ` ),
442
+ "cortex_bucket_index_loaded" ,
443
+ ))
444
+
445
+ // Try to get the index again. We expect no load attempt because the error has been cached.
446
+ prevLoads = testutil .ToFloat64 (loader .loadAttempts )
447
+ actualIdx , err = loader .GetIndex (ctx , "user-1" )
448
+ assert .Equal (t , ErrIndexNotFound , err )
449
+ assert .Nil (t , actualIdx )
450
+ assert .Equal (t , prevLoads , testutil .ToFloat64 (loader .loadAttempts ))
451
+ }
452
+
298
453
func TestLoader_ShouldOffloadIndexIfNotFoundDuringBackgroundUpdates (t * testing.T ) {
299
454
ctx := context .Background ()
300
455
reg := prometheus .NewPedanticRegistry ()
0 commit comments