mirror of
https://github.com/prometheus/prometheus
synced 2025-01-30 03:33:32 +00:00
Clarify postings index semantics, handle staleness
The postings list index may point to series that no longer exist during garbage collection. This clarifies that this is valid behavior. It would be possible, though more complex, to always keep them in sync. However, series existance means nothing in itself as the queried time range defines whether there's actual data. Thus our definition is sane overall as long as drift is kept small.
This commit is contained in:
parent
6e94145515
commit
665955da48
9
head.go
9
head.go
@ -833,24 +833,17 @@ func (h *headIndexReader) SortedPostings(p Postings) Postings {
|
||||
if err := p.Err(); err != nil {
|
||||
return errPostings{err: errors.Wrap(err, "expand postings")}
|
||||
}
|
||||
var err error
|
||||
|
||||
sort.Slice(ep, func(i, j int) bool {
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
a := h.head.series.getByID(ep[i])
|
||||
b := h.head.series.getByID(ep[j])
|
||||
|
||||
if a == nil || b == nil {
|
||||
err = errors.Errorf("series not found")
|
||||
level.Debug(h.head.logger).Log("msg", "looked up series not found")
|
||||
return false
|
||||
}
|
||||
return labels.Compare(a.lset, b.lset) < 0
|
||||
})
|
||||
if err != nil {
|
||||
return errPostings{err: err}
|
||||
}
|
||||
return newListPostings(ep)
|
||||
}
|
||||
|
||||
|
3
index.go
3
index.go
@ -525,6 +525,8 @@ type IndexReader interface {
|
||||
|
||||
// Postings returns the postings list iterator for the label pair.
|
||||
// The Postings here contain the offsets to the series inside the index.
|
||||
// Found IDs are not strictly required to point to a valid Series, e.g. during
|
||||
// background garbage collections.
|
||||
Postings(name, value string) (Postings, error)
|
||||
|
||||
// SortedPostings returns a postings list that is reordered to be sorted
|
||||
@ -533,6 +535,7 @@ type IndexReader interface {
|
||||
|
||||
// Series populates the given labels and chunk metas for the series identified
|
||||
// by the reference.
|
||||
// Returns ErrNotFound if the ref does not resolve to a known series.
|
||||
Series(ref uint64, lset *labels.Labels, chks *[]ChunkMeta) error
|
||||
|
||||
// LabelIndices returns the label pairs for which indices exist.
|
||||
|
@ -450,6 +450,10 @@ Outer:
|
||||
for s.p.Next() {
|
||||
ref := s.p.At()
|
||||
if err := s.index.Series(ref, &lset, &chunks); err != nil {
|
||||
// Postings may be stale. Skip if no underlying series exists.
|
||||
if errors.Cause(err) == ErrNotFound {
|
||||
continue
|
||||
}
|
||||
s.err = err
|
||||
return false
|
||||
}
|
||||
|
@ -702,9 +702,8 @@ func TestBaseChunkSeries(t *testing.T) {
|
||||
ref: 108,
|
||||
},
|
||||
},
|
||||
postings: []uint64{12, 10, 108},
|
||||
|
||||
expIdxs: []int{0, 1, 3},
|
||||
postings: []uint64{12, 13, 10, 108}, // 13 doesn't exist and should just be skipped over.
|
||||
expIdxs: []int{0, 1, 3},
|
||||
},
|
||||
{
|
||||
series: []refdSeries{
|
||||
@ -718,12 +717,11 @@ func TestBaseChunkSeries(t *testing.T) {
|
||||
{
|
||||
lset: labels.New([]labels.Label{{"b", "c"}}...),
|
||||
chunks: []ChunkMeta{{Ref: 8282}},
|
||||
ref: 1,
|
||||
ref: 3,
|
||||
},
|
||||
},
|
||||
postings: []uint64{},
|
||||
|
||||
expIdxs: []int{},
|
||||
expIdxs: []int{},
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user