github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/storage/tsdb/bucketindex/loader_test.go (about) 1 package bucketindex 2 3 import ( 4 "bytes" 5 "context" 6 "path" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/go-kit/log" 12 "github.com/grafana/dskit/services" 13 "github.com/oklog/ulid" 14 "github.com/prometheus/client_golang/prometheus" 15 "github.com/prometheus/client_golang/prometheus/testutil" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 19 cortex_testutil "github.com/cortexproject/cortex/pkg/storage/tsdb/testutil" 20 "github.com/cortexproject/cortex/pkg/util/test" 21 ) 22 23 func TestLoader_GetIndex_ShouldLazyLoadBucketIndex(t *testing.T) { 24 ctx := context.Background() 25 reg := prometheus.NewPedanticRegistry() 26 bkt, _ := cortex_testutil.PrepareFilesystemBucket(t) 27 28 // Create a bucket index. 29 idx := &Index{ 30 Version: IndexVersion1, 31 Blocks: Blocks{ 32 {ID: ulid.MustNew(1, nil), MinTime: 10, MaxTime: 20}, 33 }, 34 BlockDeletionMarks: nil, 35 UpdatedAt: time.Now().Unix(), 36 } 37 require.NoError(t, WriteIndex(ctx, bkt, "user-1", nil, idx)) 38 39 // Create the loader. 40 loader := NewLoader(prepareLoaderConfig(), bkt, nil, log.NewNopLogger(), reg) 41 require.NoError(t, services.StartAndAwaitRunning(ctx, loader)) 42 t.Cleanup(func() { 43 require.NoError(t, services.StopAndAwaitTerminated(ctx, loader)) 44 }) 45 46 // Ensure no index has been loaded yet. 47 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 48 # HELP cortex_bucket_index_load_failures_total Total number of bucket index loading failures. 49 # TYPE cortex_bucket_index_load_failures_total counter 50 cortex_bucket_index_load_failures_total 0 51 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 52 # TYPE cortex_bucket_index_loaded gauge 53 cortex_bucket_index_loaded 0 54 # HELP cortex_bucket_index_loads_total Total number of bucket index loading attempts. 55 # TYPE cortex_bucket_index_loads_total counter 56 cortex_bucket_index_loads_total 0 57 `), 58 "cortex_bucket_index_loads_total", 59 "cortex_bucket_index_load_failures_total", 60 "cortex_bucket_index_loaded", 61 )) 62 63 // Request the index multiple times. 64 for i := 0; i < 10; i++ { 65 actualIdx, err := loader.GetIndex(ctx, "user-1") 66 require.NoError(t, err) 67 assert.Equal(t, idx, actualIdx) 68 } 69 70 // Ensure metrics have been updated accordingly. 71 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 72 # HELP cortex_bucket_index_load_failures_total Total number of bucket index loading failures. 73 # TYPE cortex_bucket_index_load_failures_total counter 74 cortex_bucket_index_load_failures_total 0 75 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 76 # TYPE cortex_bucket_index_loaded gauge 77 cortex_bucket_index_loaded 1 78 # HELP cortex_bucket_index_loads_total Total number of bucket index loading attempts. 79 # TYPE cortex_bucket_index_loads_total counter 80 cortex_bucket_index_loads_total 1 81 `), 82 "cortex_bucket_index_loads_total", 83 "cortex_bucket_index_load_failures_total", 84 "cortex_bucket_index_loaded", 85 )) 86 } 87 88 func TestLoader_GetIndex_ShouldCacheError(t *testing.T) { 89 ctx := context.Background() 90 reg := prometheus.NewPedanticRegistry() 91 bkt, _ := cortex_testutil.PrepareFilesystemBucket(t) 92 93 // Create the loader. 94 loader := NewLoader(prepareLoaderConfig(), bkt, nil, log.NewNopLogger(), reg) 95 require.NoError(t, services.StartAndAwaitRunning(ctx, loader)) 96 t.Cleanup(func() { 97 require.NoError(t, services.StopAndAwaitTerminated(ctx, loader)) 98 }) 99 100 // Write a corrupted index. 101 require.NoError(t, bkt.Upload(ctx, path.Join("user-1", IndexCompressedFilename), strings.NewReader("invalid!}"))) 102 103 // Request the index multiple times. 104 for i := 0; i < 10; i++ { 105 _, err := loader.GetIndex(ctx, "user-1") 106 require.Equal(t, ErrIndexCorrupted, err) 107 } 108 109 // Ensure metrics have been updated accordingly. 110 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 111 # HELP cortex_bucket_index_load_failures_total Total number of bucket index loading failures. 112 # TYPE cortex_bucket_index_load_failures_total counter 113 cortex_bucket_index_load_failures_total 1 114 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 115 # TYPE cortex_bucket_index_loaded gauge 116 cortex_bucket_index_loaded 0 117 # HELP cortex_bucket_index_loads_total Total number of bucket index loading attempts. 118 # TYPE cortex_bucket_index_loads_total counter 119 cortex_bucket_index_loads_total 1 120 `), 121 "cortex_bucket_index_loads_total", 122 "cortex_bucket_index_load_failures_total", 123 "cortex_bucket_index_loaded", 124 )) 125 } 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, nil, 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 163 func TestLoader_ShouldUpdateIndexInBackgroundOnPreviousLoadSuccess(t *testing.T) { 164 ctx := context.Background() 165 reg := prometheus.NewPedanticRegistry() 166 bkt, _ := cortex_testutil.PrepareFilesystemBucket(t) 167 168 // Create a bucket index. 169 idx := &Index{ 170 Version: IndexVersion1, 171 Blocks: Blocks{ 172 {ID: ulid.MustNew(1, nil), MinTime: 10, MaxTime: 20}, 173 }, 174 BlockDeletionMarks: nil, 175 UpdatedAt: time.Now().Unix(), 176 } 177 require.NoError(t, WriteIndex(ctx, bkt, "user-1", nil, idx)) 178 179 // Create the loader. 180 cfg := LoaderConfig{ 181 CheckInterval: time.Second, 182 UpdateOnStaleInterval: time.Second, 183 UpdateOnErrorInterval: time.Hour, // Intentionally high to not hit it. 184 IdleTimeout: time.Hour, // Intentionally high to not hit it. 185 } 186 187 loader := NewLoader(cfg, bkt, nil, log.NewNopLogger(), reg) 188 require.NoError(t, services.StartAndAwaitRunning(ctx, loader)) 189 t.Cleanup(func() { 190 require.NoError(t, services.StopAndAwaitTerminated(ctx, loader)) 191 }) 192 193 actualIdx, err := loader.GetIndex(ctx, "user-1") 194 require.NoError(t, err) 195 assert.Equal(t, idx, actualIdx) 196 197 // Update the bucket index. 198 idx.Blocks = append(idx.Blocks, &Block{ID: ulid.MustNew(2, nil), MinTime: 20, MaxTime: 30}) 199 require.NoError(t, WriteIndex(ctx, bkt, "user-1", nil, idx)) 200 201 // Wait until the index has been updated in background. 202 test.Poll(t, 3*time.Second, 2, func() interface{} { 203 actualIdx, err := loader.GetIndex(ctx, "user-1") 204 if err != nil { 205 return 0 206 } 207 return len(actualIdx.Blocks) 208 }) 209 210 actualIdx, err = loader.GetIndex(ctx, "user-1") 211 require.NoError(t, err) 212 assert.Equal(t, idx, actualIdx) 213 214 // Ensure metrics have been updated accordingly. 215 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 216 # HELP cortex_bucket_index_load_failures_total Total number of bucket index loading failures. 217 # TYPE cortex_bucket_index_load_failures_total counter 218 cortex_bucket_index_load_failures_total 0 219 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 220 # TYPE cortex_bucket_index_loaded gauge 221 cortex_bucket_index_loaded 1 222 `), 223 "cortex_bucket_index_load_failures_total", 224 "cortex_bucket_index_loaded", 225 )) 226 } 227 228 func TestLoader_ShouldUpdateIndexInBackgroundOnPreviousLoadFailure(t *testing.T) { 229 ctx := context.Background() 230 reg := prometheus.NewPedanticRegistry() 231 bkt, _ := cortex_testutil.PrepareFilesystemBucket(t) 232 233 // Write a corrupted index. 234 require.NoError(t, bkt.Upload(ctx, path.Join("user-1", IndexCompressedFilename), strings.NewReader("invalid!}"))) 235 236 // Create the loader. 237 cfg := LoaderConfig{ 238 CheckInterval: time.Second, 239 UpdateOnStaleInterval: time.Hour, // Intentionally high to not hit it. 240 UpdateOnErrorInterval: time.Second, 241 IdleTimeout: time.Hour, // Intentionally high to not hit it. 242 } 243 244 loader := NewLoader(cfg, bkt, nil, log.NewNopLogger(), reg) 245 require.NoError(t, services.StartAndAwaitRunning(ctx, loader)) 246 t.Cleanup(func() { 247 require.NoError(t, services.StopAndAwaitTerminated(ctx, loader)) 248 }) 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", nil, 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, nil, 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 303 _, err := loader.GetIndex(ctx, "user-1") 304 assert.Equal(t, ErrIndexNotFound, err) 305 306 // Upload the bucket index. 307 idx := &Index{ 308 Version: IndexVersion1, 309 Blocks: Blocks{ 310 {ID: ulid.MustNew(1, nil), MinTime: 10, MaxTime: 20}, 311 }, 312 BlockDeletionMarks: nil, 313 UpdatedAt: time.Now().Unix(), 314 } 315 require.NoError(t, WriteIndex(ctx, bkt, "user-1", nil, idx)) 316 317 // Wait until the index has been updated in background. 318 test.Poll(t, 3*time.Second, nil, func() interface{} { 319 _, err := loader.GetIndex(ctx, "user-1") 320 return err 321 }) 322 323 actualIdx, err := loader.GetIndex(ctx, "user-1") 324 require.NoError(t, err) 325 assert.Equal(t, idx, actualIdx) 326 327 // Ensure metrics have been updated accordingly. 328 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 329 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 330 # TYPE cortex_bucket_index_loaded gauge 331 cortex_bucket_index_loaded 1 332 `), 333 "cortex_bucket_index_loaded", 334 )) 335 } 336 337 func TestLoader_ShouldNotCacheCriticalErrorOnBackgroundUpdates(t *testing.T) { 338 ctx := context.Background() 339 reg := prometheus.NewPedanticRegistry() 340 bkt, _ := cortex_testutil.PrepareFilesystemBucket(t) 341 342 // Create a bucket index. 343 idx := &Index{ 344 Version: IndexVersion1, 345 Blocks: Blocks{ 346 {ID: ulid.MustNew(1, nil), MinTime: 10, MaxTime: 20}, 347 }, 348 BlockDeletionMarks: nil, 349 UpdatedAt: time.Now().Unix(), 350 } 351 require.NoError(t, WriteIndex(ctx, bkt, "user-1", nil, idx)) 352 353 // Create the loader. 354 cfg := LoaderConfig{ 355 CheckInterval: time.Second, 356 UpdateOnStaleInterval: time.Second, 357 UpdateOnErrorInterval: time.Second, 358 IdleTimeout: time.Hour, // Intentionally high to not hit it. 359 } 360 361 loader := NewLoader(cfg, bkt, nil, log.NewNopLogger(), reg) 362 require.NoError(t, services.StartAndAwaitRunning(ctx, loader)) 363 t.Cleanup(func() { 364 require.NoError(t, services.StopAndAwaitTerminated(ctx, loader)) 365 }) 366 367 actualIdx, err := loader.GetIndex(ctx, "user-1") 368 require.NoError(t, err) 369 assert.Equal(t, idx, actualIdx) 370 371 // Write a corrupted index. 372 require.NoError(t, bkt.Upload(ctx, path.Join("user-1", IndexCompressedFilename), strings.NewReader("invalid!}"))) 373 374 // Wait until the first failure has been tracked. 375 test.Poll(t, 3*time.Second, true, func() interface{} { 376 return testutil.ToFloat64(loader.loadFailures) > 0 377 }) 378 379 actualIdx, err = loader.GetIndex(ctx, "user-1") 380 require.NoError(t, err) 381 assert.Equal(t, idx, actualIdx) 382 383 // Ensure metrics have been updated accordingly. 384 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 385 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 386 # TYPE cortex_bucket_index_loaded gauge 387 cortex_bucket_index_loaded 1 388 `), 389 "cortex_bucket_index_loaded", 390 )) 391 } 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", nil, 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, nil, 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", nil)) 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 453 func TestLoader_ShouldOffloadIndexIfNotFoundDuringBackgroundUpdates(t *testing.T) { 454 ctx := context.Background() 455 reg := prometheus.NewPedanticRegistry() 456 bkt, _ := cortex_testutil.PrepareFilesystemBucket(t) 457 458 // Create a bucket index. 459 idx := &Index{ 460 Version: IndexVersion1, 461 Blocks: Blocks{ 462 {ID: ulid.MustNew(1, nil), MinTime: 10, MaxTime: 20}, 463 }, 464 BlockDeletionMarks: nil, 465 UpdatedAt: time.Now().Unix(), 466 } 467 require.NoError(t, WriteIndex(ctx, bkt, "user-1", nil, idx)) 468 469 // Create the loader. 470 cfg := LoaderConfig{ 471 CheckInterval: time.Second, 472 UpdateOnStaleInterval: time.Second, 473 UpdateOnErrorInterval: time.Second, 474 IdleTimeout: time.Hour, // Intentionally high to not hit it. 475 } 476 477 loader := NewLoader(cfg, bkt, nil, log.NewNopLogger(), reg) 478 require.NoError(t, services.StartAndAwaitRunning(ctx, loader)) 479 t.Cleanup(func() { 480 require.NoError(t, services.StopAndAwaitTerminated(ctx, loader)) 481 }) 482 483 actualIdx, err := loader.GetIndex(ctx, "user-1") 484 require.NoError(t, err) 485 assert.Equal(t, idx, actualIdx) 486 487 // Delete the index 488 require.NoError(t, DeleteIndex(ctx, bkt, "user-1", nil)) 489 490 // Wait until the index is offloaded. 491 test.Poll(t, 3*time.Second, float64(0), func() interface{} { 492 return testutil.ToFloat64(loader.loaded) 493 }) 494 495 _, err = loader.GetIndex(ctx, "user-1") 496 require.Equal(t, ErrIndexNotFound, err) 497 498 // Ensure metrics have been updated accordingly. 499 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 500 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 501 # TYPE cortex_bucket_index_loaded gauge 502 cortex_bucket_index_loaded 0 503 `), 504 "cortex_bucket_index_loaded", 505 )) 506 } 507 508 func TestLoader_ShouldOffloadIndexIfIdleTimeoutIsReachedDuringBackgroundUpdates(t *testing.T) { 509 ctx := context.Background() 510 reg := prometheus.NewPedanticRegistry() 511 bkt, _ := cortex_testutil.PrepareFilesystemBucket(t) 512 513 // Create a bucket index. 514 idx := &Index{ 515 Version: IndexVersion1, 516 Blocks: Blocks{ 517 {ID: ulid.MustNew(1, nil), MinTime: 10, MaxTime: 20}, 518 }, 519 BlockDeletionMarks: nil, 520 UpdatedAt: time.Now().Unix(), 521 } 522 require.NoError(t, WriteIndex(ctx, bkt, "user-1", nil, idx)) 523 524 // Create the loader. 525 cfg := LoaderConfig{ 526 CheckInterval: time.Second, 527 UpdateOnStaleInterval: time.Second, 528 UpdateOnErrorInterval: time.Second, 529 IdleTimeout: 0, // Offload at first check. 530 } 531 532 loader := NewLoader(cfg, bkt, nil, log.NewNopLogger(), reg) 533 require.NoError(t, services.StartAndAwaitRunning(ctx, loader)) 534 t.Cleanup(func() { 535 require.NoError(t, services.StopAndAwaitTerminated(ctx, loader)) 536 }) 537 538 actualIdx, err := loader.GetIndex(ctx, "user-1") 539 require.NoError(t, err) 540 assert.Equal(t, idx, actualIdx) 541 542 // Wait until the index is offloaded. 543 test.Poll(t, 3*time.Second, float64(0), func() interface{} { 544 return testutil.ToFloat64(loader.loaded) 545 }) 546 547 // Ensure metrics have been updated accordingly. 548 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 549 # HELP cortex_bucket_index_loaded Number of bucket indexes currently loaded in-memory. 550 # TYPE cortex_bucket_index_loaded gauge 551 cortex_bucket_index_loaded 0 552 # HELP cortex_bucket_index_loads_total Total number of bucket index loading attempts. 553 # TYPE cortex_bucket_index_loads_total counter 554 cortex_bucket_index_loads_total 1 555 `), 556 "cortex_bucket_index_loaded", 557 "cortex_bucket_index_loads_total", 558 )) 559 560 // Load it again. 561 actualIdx, err = loader.GetIndex(ctx, "user-1") 562 require.NoError(t, err) 563 assert.Equal(t, idx, actualIdx) 564 565 // Ensure metrics have been updated accordingly. 566 assert.NoError(t, testutil.GatherAndCompare(reg, bytes.NewBufferString(` 567 # HELP cortex_bucket_index_loads_total Total number of bucket index loading attempts. 568 # TYPE cortex_bucket_index_loads_total counter 569 cortex_bucket_index_loads_total 2 570 `), 571 "cortex_bucket_index_loads_total", 572 )) 573 } 574 575 func prepareLoaderConfig() LoaderConfig { 576 return LoaderConfig{ 577 CheckInterval: time.Minute, 578 UpdateOnStaleInterval: 15 * time.Minute, 579 UpdateOnErrorInterval: time.Minute, 580 IdleTimeout: time.Hour, 581 } 582 }