Skip to content

Commit

Permalink
db: make sure blocks don't overlap
Browse files Browse the repository at this point in the history
Reduce `block.MaxTime` by 1 millisecond so that `blocks[1].MinTime ==
blocks[0].MaxTime + 1`.

This prevents chunks that start exactly at the block end (i.e.
`chunk.MinTime == block.MaxTime`) from being included in that block.

See prometheus-junkyard#347 for a detailed explanation.

Signed-off-by: Benoît Knecht <benoit.knecht@fsfe.org>
  • Loading branch information
BenoitKnecht committed Jun 18, 2018
1 parent c848349 commit 7b56afb
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 3 deletions.
7 changes: 5 additions & 2 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ func (db *DB) reload(deleteable ...string) (err error) {
if len(blocks) == 0 {
return nil
}
maxt := blocks[len(blocks)-1].Meta().MaxTime
maxt := blocks[len(blocks)-1].Meta().MaxTime + 1

return errors.Wrap(db.head.Truncate(maxt), "head truncate failed")
}
Expand Down Expand Up @@ -805,9 +805,12 @@ func (db *DB) Querier(mint, maxt int64) (Querier, error) {
return sq, nil
}

// Returns a closed time interval that contains t, with its lower boundary
// aligned on a multiple of width. The upper boundary is such that the next
// interval is contiguous without overlapping.
func rangeForTimestamp(t int64, width int64) (mint, maxt int64) {
mint = (t / width) * width
return mint, mint + width
return mint, mint + width - 1
}

// Delete implements deletion of metrics. It only has atomicity guarantees on a per-block basis.
Expand Down
5 changes: 4 additions & 1 deletion head.go
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,10 @@ func (s *memSeries) cut(mint int64) *memChunk {

// Set upper bound on when the next chunk must be started. An earlier timestamp
// may be chosen dynamically at a later point.
_, s.nextAt = rangeForTimestamp(mint, s.chunkRange)
_, maxt := rangeForTimestamp(mint, s.chunkRange)
// rangeForTimestamp() returns the maximum timestamp for the previous
// chunk; we want to cut right after that, so we add 1 millisecond
s.nextAt = maxt + 1

app, err := c.chunk.Appender()
if err != nil {
Expand Down

0 comments on commit 7b56afb

Please sign in to comment.