mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-26 06:04:05 -08:00
New cases in Test_ChunkQuerier_OOOQuery and Test_Querier_OOOQuery
Case 1: OOO in-memory head chunk overlaps with first mmaped in-order chunk.
Query: |----------------------------------------------------------------|
InO: |------mmap---------------||---------mem----------------------|
OOO: |-----mem-----------|
This triggers ChunkOrIterableWithCopy not including OOO head chunks bug.
Similar to #14693 however testing the end of the interval doesn't
trigger the problem because there the in-order head chunk will be
trimmed with a tombstone, causing the code to switch to ChunkOrIterable
which was fixed.
See a36d1a8a92/tsdb/querier.go (L646)
where len(p.bufIter.Intervals) will be non zero, because it includes the
tombstone to trim the result to the query max time.
Thus a new test is added to check the overlap at the beginning of the
interval that has a separate chunk, which does not need trimming.
Note: same test doesn't fail for sample querier in Test_Querier_OOOQuery
as that doesn't use copy, that is copyHeadChunk is false in the if
condition above.
Case 2:
OOO mmaped head chunk overlaps with first mmaped in-order chunk.
Query: |----------------------------------------------------------------|
InO: |------mmap---------------||---------mem----------------------|
OOO: |-----mmap-----------| |--mem--|
In this case the meta contains the reference of the in-order chunk and
no indication that a merge is needed with the OOO mmaped chunk.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
This commit is contained in:
parent
0538ad3a08
commit
41c076196e
377
tsdb/db_test.go
377
tsdb/db_test.go
|
@ -5036,16 +5036,15 @@ func testOOOQueryAfterRestartWithSnapshotAndRemovedWBL(t *testing.T, scenario sa
|
||||||
|
|
||||||
func Test_Querier_OOOQuery(t *testing.T) {
|
func Test_Querier_OOOQuery(t *testing.T) {
|
||||||
opts := DefaultOptions()
|
opts := DefaultOptions()
|
||||||
opts.OutOfOrderCapMax = 30
|
|
||||||
opts.OutOfOrderTimeWindow = 24 * time.Hour.Milliseconds()
|
opts.OutOfOrderTimeWindow = 24 * time.Hour.Milliseconds()
|
||||||
|
|
||||||
series1 := labels.FromStrings("foo", "bar1")
|
series1 := labels.FromStrings("foo", "bar1")
|
||||||
|
|
||||||
|
type filterFunc func(t int64) bool
|
||||||
|
defaultFilterFunc := func(t int64) bool { return true }
|
||||||
|
|
||||||
minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() }
|
minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() }
|
||||||
addSample := func(db *DB, fromMins, toMins, queryMinT, queryMaxT int64, expSamples []chunks.Sample, filter func(int64) bool) ([]chunks.Sample, int) {
|
addSample := func(db *DB, fromMins, toMins, queryMinT, queryMaxT int64, expSamples []chunks.Sample, filter filterFunc) ([]chunks.Sample, int) {
|
||||||
if filter == nil {
|
|
||||||
filter = func(int64) bool { return true }
|
|
||||||
}
|
|
||||||
app := db.Appender(context.Background())
|
app := db.Appender(context.Background())
|
||||||
totalAppended := 0
|
totalAppended := 0
|
||||||
for m := fromMins; m <= toMins; m += time.Minute.Milliseconds() {
|
for m := fromMins; m <= toMins; m += time.Minute.Milliseconds() {
|
||||||
|
@ -5060,68 +5059,173 @@ func Test_Querier_OOOQuery(t *testing.T) {
|
||||||
totalAppended++
|
totalAppended++
|
||||||
}
|
}
|
||||||
require.NoError(t, app.Commit())
|
require.NoError(t, app.Commit())
|
||||||
|
require.Positive(t, totalAppended, 0) // Sanity check that filter is not too zealous.
|
||||||
return expSamples, totalAppended
|
return expSamples, totalAppended
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sampleBatch struct {
|
||||||
|
minT int64
|
||||||
|
maxT int64
|
||||||
|
filter filterFunc
|
||||||
|
isOOO bool
|
||||||
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
queryMinT int64
|
oooCap int64
|
||||||
queryMaxT int64
|
queryMinT int64
|
||||||
inOrderMinT int64
|
queryMaxT int64
|
||||||
inOrderMaxT int64
|
batches []sampleBatch
|
||||||
oooMinT int64
|
|
||||||
oooMaxT int64
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "query interval covering ooomint and inordermaxt returns all ingested samples",
|
name: "query interval covering ooomint and inordermaxt returns all ingested samples",
|
||||||
queryMinT: minutes(0),
|
oooCap: 30,
|
||||||
queryMaxT: minutes(200),
|
queryMinT: minutes(0),
|
||||||
inOrderMinT: minutes(100),
|
queryMaxT: minutes(200),
|
||||||
inOrderMaxT: minutes(200),
|
batches: []sampleBatch{
|
||||||
oooMinT: minutes(0),
|
{
|
||||||
oooMaxT: minutes(99),
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(0),
|
||||||
|
maxT: minutes(99),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "partial query interval returns only samples within interval",
|
name: "partial query interval returns only samples within interval",
|
||||||
queryMinT: minutes(20),
|
oooCap: 30,
|
||||||
queryMaxT: minutes(180),
|
queryMinT: minutes(20),
|
||||||
inOrderMinT: minutes(100),
|
queryMaxT: minutes(180),
|
||||||
inOrderMaxT: minutes(200),
|
batches: []sampleBatch{
|
||||||
oooMinT: minutes(0),
|
{
|
||||||
oooMaxT: minutes(99),
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(0),
|
||||||
|
maxT: minutes(99),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "query overlapping inorder and ooo samples returns all ingested samples",
|
name: "query overlapping inorder and ooo samples returns all ingested samples at the end of the interval",
|
||||||
queryMinT: minutes(0),
|
oooCap: 30,
|
||||||
queryMaxT: minutes(200),
|
queryMinT: minutes(0),
|
||||||
inOrderMinT: minutes(100),
|
queryMaxT: minutes(200),
|
||||||
inOrderMaxT: minutes(200),
|
batches: []sampleBatch{
|
||||||
oooMinT: minutes(180 - opts.OutOfOrderCapMax/2), // Make sure to fit into the OOO head.
|
{
|
||||||
oooMaxT: minutes(180),
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(170),
|
||||||
|
maxT: minutes(180),
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query overlapping inorder and ooo in-memory samples returns all ingested samples at the beginning of the interval",
|
||||||
|
oooCap: 30,
|
||||||
|
queryMinT: minutes(0),
|
||||||
|
queryMaxT: minutes(200),
|
||||||
|
batches: []sampleBatch{
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(110),
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query inorder contain ooo mmaped samples returns all ingested samples at the beginning of the interval",
|
||||||
|
oooCap: 5,
|
||||||
|
queryMinT: minutes(0),
|
||||||
|
queryMaxT: minutes(200),
|
||||||
|
batches: []sampleBatch{
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(101),
|
||||||
|
maxT: minutes(101 + (5-1)*2), // Append samples to fit in a single mmmaped OOO chunk and fit inside the first in-order mmaped chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(191),
|
||||||
|
maxT: minutes(193), // Append some more OOO samples to trigger mapping the OOO chunk, but use time 151 to not overlap with in-order head chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query overlapping inorder and ooo mmaped samples returns all ingested samples at the beginning of the interval",
|
||||||
|
oooCap: 30,
|
||||||
|
queryMinT: minutes(0),
|
||||||
|
queryMaxT: minutes(200),
|
||||||
|
batches: []sampleBatch{
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(101),
|
||||||
|
maxT: minutes(101 + (30-1)*2), // Append samples to fit in a single mmmaped OOO chunk and overlap the first in-order mmaped chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(191),
|
||||||
|
maxT: minutes(193), // Append some more OOO samples to trigger mapping the OOO chunk, but use time 151 to not overlap with in-order head chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(fmt.Sprintf("name=%s", tc.name), func(t *testing.T) {
|
t.Run(fmt.Sprintf("name=%s", tc.name), func(t *testing.T) {
|
||||||
|
opts.OutOfOrderCapMax = tc.oooCap
|
||||||
db := openTestDB(t, opts, nil)
|
db := openTestDB(t, opts, nil)
|
||||||
db.DisableCompactions()
|
db.DisableCompactions()
|
||||||
defer func() {
|
defer func() {
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var (
|
var expSamples []chunks.Sample
|
||||||
expSamples []chunks.Sample
|
var oooSamples, appendedCount int
|
||||||
inoSamples int
|
|
||||||
)
|
|
||||||
|
|
||||||
// Add in-order samples (at even minutes).
|
for _, batch := range tc.batches {
|
||||||
expSamples, inoSamples = addSample(db, tc.inOrderMinT, tc.inOrderMaxT, tc.queryMinT, tc.queryMaxT, expSamples, func(t int64) bool { return t%2 == 0 })
|
expSamples, appendedCount = addSample(db, batch.minT, batch.maxT, tc.queryMinT, tc.queryMaxT, expSamples, batch.filter)
|
||||||
// Sanity check that filter is not too zealous.
|
if batch.isOOO {
|
||||||
require.Positive(t, inoSamples, 0)
|
oooSamples += appendedCount
|
||||||
|
}
|
||||||
// Add out-of-order samples (at odd minutes).
|
}
|
||||||
expSamples, oooSamples := addSample(db, tc.oooMinT, tc.oooMaxT, tc.queryMinT, tc.queryMaxT, expSamples, func(t int64) bool { return t%2 == 1 })
|
|
||||||
// Sanity check that filter is not too zealous.
|
|
||||||
require.Positive(t, oooSamples, 0)
|
|
||||||
|
|
||||||
sort.Slice(expSamples, func(i, j int) bool {
|
sort.Slice(expSamples, func(i, j int) bool {
|
||||||
return expSamples[i].T() < expSamples[j].T()
|
return expSamples[i].T() < expSamples[j].T()
|
||||||
|
@ -5147,11 +5251,17 @@ func Test_ChunkQuerier_OOOQuery(t *testing.T) {
|
||||||
|
|
||||||
series1 := labels.FromStrings("foo", "bar1")
|
series1 := labels.FromStrings("foo", "bar1")
|
||||||
|
|
||||||
|
type filterFunc func(t int64) bool
|
||||||
|
defaultFilterFunc := func(t int64) bool { return true }
|
||||||
|
|
||||||
minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() }
|
minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() }
|
||||||
addSample := func(db *DB, fromMins, toMins, queryMinT, queryMaxT int64, expSamples []chunks.Sample) ([]chunks.Sample, int) {
|
addSample := func(db *DB, fromMins, toMins, queryMinT, queryMaxT int64, expSamples []chunks.Sample, filter filterFunc) ([]chunks.Sample, int) {
|
||||||
app := db.Appender(context.Background())
|
app := db.Appender(context.Background())
|
||||||
totalAppended := 0
|
totalAppended := 0
|
||||||
for m := fromMins; m <= toMins; m += time.Minute.Milliseconds() {
|
for m := fromMins; m <= toMins; m += time.Minute.Milliseconds() {
|
||||||
|
if !filter(m / time.Minute.Milliseconds()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
_, err := app.Append(0, series1, m, float64(m))
|
_, err := app.Append(0, series1, m, float64(m))
|
||||||
if m >= queryMinT && m <= queryMaxT {
|
if m >= queryMinT && m <= queryMaxT {
|
||||||
expSamples = append(expSamples, sample{t: m, f: float64(m)})
|
expSamples = append(expSamples, sample{t: m, f: float64(m)})
|
||||||
|
@ -5160,39 +5270,158 @@ func Test_ChunkQuerier_OOOQuery(t *testing.T) {
|
||||||
totalAppended++
|
totalAppended++
|
||||||
}
|
}
|
||||||
require.NoError(t, app.Commit())
|
require.NoError(t, app.Commit())
|
||||||
|
require.Positive(t, totalAppended) // Sanity check that filter is not too zealous.
|
||||||
return expSamples, totalAppended
|
return expSamples, totalAppended
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sampleBatch struct {
|
||||||
|
minT int64
|
||||||
|
maxT int64
|
||||||
|
filter filterFunc
|
||||||
|
isOOO bool
|
||||||
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
queryMinT int64
|
oooCap int64
|
||||||
queryMaxT int64
|
queryMinT int64
|
||||||
inOrderMinT int64
|
queryMaxT int64
|
||||||
inOrderMaxT int64
|
batches []sampleBatch
|
||||||
oooMinT int64
|
|
||||||
oooMaxT int64
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "query interval covering ooomint and inordermaxt returns all ingested samples",
|
name: "query interval covering ooomint and inordermaxt returns all ingested samples",
|
||||||
queryMinT: minutes(0),
|
oooCap: 30,
|
||||||
queryMaxT: minutes(200),
|
queryMinT: minutes(0),
|
||||||
inOrderMinT: minutes(100),
|
queryMaxT: minutes(200),
|
||||||
inOrderMaxT: minutes(200),
|
batches: []sampleBatch{
|
||||||
oooMinT: minutes(0),
|
{
|
||||||
oooMaxT: minutes(99),
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(0),
|
||||||
|
maxT: minutes(99),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "partial query interval returns only samples within interval",
|
name: "partial query interval returns only samples within interval",
|
||||||
queryMinT: minutes(20),
|
oooCap: 30,
|
||||||
queryMaxT: minutes(180),
|
queryMinT: minutes(20),
|
||||||
inOrderMinT: minutes(100),
|
queryMaxT: minutes(180),
|
||||||
inOrderMaxT: minutes(200),
|
batches: []sampleBatch{
|
||||||
oooMinT: minutes(0),
|
{
|
||||||
oooMaxT: minutes(99),
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(0),
|
||||||
|
maxT: minutes(99),
|
||||||
|
filter: defaultFilterFunc,
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query overlapping inorder and ooo samples returns all ingested samples at the end of the interval",
|
||||||
|
oooCap: 30,
|
||||||
|
queryMinT: minutes(0),
|
||||||
|
queryMaxT: minutes(200),
|
||||||
|
batches: []sampleBatch{
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(170),
|
||||||
|
maxT: minutes(180),
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query overlapping inorder and ooo in-memory samples returns all ingested samples at the beginning of the interval",
|
||||||
|
oooCap: 30,
|
||||||
|
queryMinT: minutes(0),
|
||||||
|
queryMaxT: minutes(200),
|
||||||
|
batches: []sampleBatch{
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(110),
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query inorder contain ooo mmaped samples returns all ingested samples at the beginning of the interval",
|
||||||
|
oooCap: 5,
|
||||||
|
queryMinT: minutes(0),
|
||||||
|
queryMaxT: minutes(200),
|
||||||
|
batches: []sampleBatch{
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(101),
|
||||||
|
maxT: minutes(101 + (5-1)*2), // Append samples to fit in a single mmmaped OOO chunk and fit inside the first in-order mmaped chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(191),
|
||||||
|
maxT: minutes(193), // Append some more OOO samples to trigger mapping the OOO chunk, but use time 151 to not overlap with in-order head chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query overlapping inorder and ooo mmaped samples returns all ingested samples at the beginning of the interval",
|
||||||
|
oooCap: 30,
|
||||||
|
queryMinT: minutes(0),
|
||||||
|
queryMaxT: minutes(200),
|
||||||
|
batches: []sampleBatch{
|
||||||
|
{
|
||||||
|
minT: minutes(100),
|
||||||
|
maxT: minutes(200),
|
||||||
|
filter: func(t int64) bool { return t%2 == 0 },
|
||||||
|
isOOO: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(101),
|
||||||
|
maxT: minutes(101 + (30-1)*2), // Append samples to fit in a single mmmaped OOO chunk and overlap the first in-order mmaped chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
minT: minutes(191),
|
||||||
|
maxT: minutes(193), // Append some more OOO samples to trigger mapping the OOO chunk, but use time 151 to not overlap with in-order head chunk.
|
||||||
|
filter: func(t int64) bool { return t%2 == 1 },
|
||||||
|
isOOO: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(fmt.Sprintf("name=%s", tc.name), func(t *testing.T) {
|
t.Run(fmt.Sprintf("name=%s", tc.name), func(t *testing.T) {
|
||||||
|
opts.OutOfOrderCapMax = tc.oooCap
|
||||||
db := openTestDB(t, opts, nil)
|
db := openTestDB(t, opts, nil)
|
||||||
db.DisableCompactions()
|
db.DisableCompactions()
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -5200,12 +5429,14 @@ func Test_ChunkQuerier_OOOQuery(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var expSamples []chunks.Sample
|
var expSamples []chunks.Sample
|
||||||
|
var oooSamples, appendedCount int
|
||||||
|
|
||||||
// Add in-order samples.
|
for _, batch := range tc.batches {
|
||||||
expSamples, _ = addSample(db, tc.inOrderMinT, tc.inOrderMaxT, tc.queryMinT, tc.queryMaxT, expSamples)
|
expSamples, appendedCount = addSample(db, batch.minT, batch.maxT, tc.queryMinT, tc.queryMaxT, expSamples, batch.filter)
|
||||||
|
if batch.isOOO {
|
||||||
// Add out-of-order samples.
|
oooSamples += appendedCount
|
||||||
expSamples, oooSamples := addSample(db, tc.oooMinT, tc.oooMaxT, tc.queryMinT, tc.queryMaxT, expSamples)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sort.Slice(expSamples, func(i, j int) bool {
|
sort.Slice(expSamples, func(i, j int) bool {
|
||||||
return expSamples[i].T() < expSamples[j].T()
|
return expSamples[i].T() < expSamples[j].T()
|
||||||
|
|
Loading…
Reference in a new issue