compactHead compacts the Head block at specified block durations avoiding a single huge block.
(ctx context.Context, blockDuration int64)
| 463 | |
| 464 | // compactHead compacts the Head block at specified block durations avoiding a single huge block. |
| 465 | func (u *userTSDB) compactHead(ctx context.Context, blockDuration int64) error { |
| 466 | if !u.casState(active, forceCompacting) { |
| 467 | return errors.New("TSDB head cannot be compacted because it is not in active state (possibly being closed or blocks shipping in progress)") |
| 468 | } |
| 469 | |
| 470 | defer u.casState(forceCompacting, active) |
| 471 | |
| 472 | // Ingestion of samples in parallel with forced compaction can lead to overlapping blocks, |
| 473 | // and possible invalidation of the references returned from Appender.GetRef(). |
| 474 | // So we wait for existing in-flight requests to finish. Future push requests would fail until compaction is over. |
| 475 | u.pushesInFlight.Wait() |
| 476 | |
| 477 | h := u.Head() |
| 478 | |
| 479 | minTime, maxTime := h.MinTime(), h.MaxTime() |
| 480 | |
| 481 | for (minTime/blockDuration)*blockDuration != (maxTime/blockDuration)*blockDuration { |
| 482 | // Data in Head spans across multiple block ranges, so we break it into blocks here. |
| 483 | // Block max time is exclusive, so we do a -1 here. |
| 484 | blockMaxTime := ((minTime/blockDuration)+1)*blockDuration - 1 |
| 485 | if err := u.db.CompactHead(tsdb.NewRangeHead(h, minTime, blockMaxTime)); err != nil { |
| 486 | return err |
| 487 | } |
| 488 | |
| 489 | // Get current min/max times after compaction. |
| 490 | minTime, maxTime = h.MinTime(), h.MaxTime() |
| 491 | } |
| 492 | |
| 493 | if err := u.db.CompactHead(tsdb.NewRangeHead(h, minTime, maxTime)); err != nil { |
| 494 | return err |
| 495 | } |
| 496 | return u.db.CompactOOOHead(ctx) |
| 497 | } |
| 498 | |
| 499 | // PreCreation implements SeriesLifecycleCallback interface. |
| 500 | func (u *userTSDB) PreCreation(metric labels.Labels) error { |
no test coverage detected