@@ -334,6 +334,109 @@ func TestAggMetricIngestFrom(t *testing.T) {
334
334
}
335
335
}
336
336
337
+ // TestAggMetricFutureTolerance tests whether the future tolerance limit works correctly
338
+ // there is a race condition because it depends on the return value of time.Now().Unix(),
339
+ // realistically it should never fail due to that race condition unless it executes
340
+ // unreasonably slow.
341
+ func TestAggMetricFutureTolerance (t * testing.T ) {
342
+ cluster .Init ("default" , "test" , time .Now (), "http" , 6060 )
343
+ cluster .Manager .SetPrimary (true )
344
+ mockstore .Reset ()
345
+ ret := conf .MustParseRetentions ("1s:10m:6h:5:true" )
346
+
347
+ _futureToleranceRatio := futureToleranceRatio
348
+ _enforceFutureTolerance := enforceFutureTolerance
349
+ discardedSampleTooFarAhead .SetUint32 (0 )
350
+ sampleTooFarAhead .SetUint32 (0 )
351
+ defer func () {
352
+ futureToleranceRatio = _futureToleranceRatio
353
+ enforceFutureTolerance = _enforceFutureTolerance
354
+ discardedSampleTooFarAhead .SetUint32 (0 )
355
+ sampleTooFarAhead .SetUint32 (0 )
356
+ }()
357
+
358
+ // with a raw retention of 600s, this will result in a future tolerance of 60s
359
+ futureToleranceRatio = 10
360
+ aggMetricTolerate60 := NewAggMetric (mockstore , & cache.MockCache {}, test .GetAMKey (42 ), ret , 0 , 1 , nil , false , false , 0 )
361
+
362
+ // will not tolerate future datapoints at all
363
+ futureToleranceRatio = 0
364
+ aggMetricTolerate0 := NewAggMetric (mockstore , & cache.MockCache {}, test .GetAMKey (42 ), ret , 0 , 1 , nil , false , false , 0 )
365
+
366
+ // add datapoint which is 30 seconds in the future to both aggmetrics, they should both accept it
367
+ // because enforcement of future tolerance is disabled, but the one with tolerance 0 should increase
368
+ // the counter of data points that would have been rejected
369
+ enforceFutureTolerance = false
370
+ aggMetricTolerate60 .Add (uint32 (time .Now ().Unix ()+ 30 ), 10 )
371
+ if len (aggMetricTolerate60 .chunks ) != 1 {
372
+ t .Fatalf ("expected to have 1 chunk in aggmetric, but there were %d" , len (aggMetricTolerate60 .chunks ))
373
+ }
374
+ if sampleTooFarAhead .Peek () != 0 {
375
+ t .Fatalf ("expected the sampleTooFarAhead count to be 0, but it was %d" , sampleTooFarAhead .Peek ())
376
+ }
377
+ if discardedSampleTooFarAhead .Peek () != 0 {
378
+ t .Fatalf ("expected the discardedSampleTooFarAhead count to be 0, but it was %d" , discardedSampleTooFarAhead .Peek ())
379
+ }
380
+
381
+ aggMetricTolerate0 .Add (uint32 (time .Now ().Unix ()+ 30 ), 10 )
382
+ if len (aggMetricTolerate0 .chunks ) != 1 {
383
+ t .Fatalf ("expected to have 1 chunk in aggmetric, but there were %d" , len (aggMetricTolerate0 .chunks ))
384
+ }
385
+ if sampleTooFarAhead .Peek () != 1 {
386
+ t .Fatalf ("expected the sampleTooFarAhead count to be 1, but it was %d" , sampleTooFarAhead .Peek ())
387
+ }
388
+ if discardedSampleTooFarAhead .Peek () != 0 {
389
+ t .Fatalf ("expected the discardedSampleTooFarAhead count to be 0, but it was %d" , discardedSampleTooFarAhead .Peek ())
390
+ }
391
+
392
+ // enable the enforcement of the future tolerance limit and re-initialize the two agg metrics
393
+ // then add a data point with time stamp 30 sec in the future to both aggmetrics again.
394
+ // this time only the one that tolerates up to 60 secs should accept the datapoint.
395
+ discardedSampleTooFarAhead .SetUint32 (0 )
396
+ sampleTooFarAhead .SetUint32 (0 )
397
+ enforceFutureTolerance = true
398
+ futureToleranceRatio = 10
399
+ aggMetricTolerate60 = NewAggMetric (mockstore , & cache.MockCache {}, test .GetAMKey (42 ), ret , 0 , 1 , nil , false , false , 0 )
400
+ futureToleranceRatio = 0
401
+ aggMetricTolerate0 = NewAggMetric (mockstore , & cache.MockCache {}, test .GetAMKey (42 ), ret , 0 , 1 , nil , false , false , 0 )
402
+
403
+ aggMetricTolerate60 .Add (uint32 (time .Now ().Unix ()+ 30 ), 10 )
404
+ if len (aggMetricTolerate60 .chunks ) != 1 {
405
+ t .Fatalf ("expected to have 1 chunk in aggmetric, but there were %d" , len (aggMetricTolerate60 .chunks ))
406
+ }
407
+ if sampleTooFarAhead .Peek () != 0 {
408
+ t .Fatalf ("expected the sampleTooFarAhead count to be 0, but it was %d" , sampleTooFarAhead .Peek ())
409
+ }
410
+ if discardedSampleTooFarAhead .Peek () != 0 {
411
+ t .Fatalf ("expected the discardedSampleTooFarAhead count to be 0, but it was %d" , discardedSampleTooFarAhead .Peek ())
412
+ }
413
+
414
+ aggMetricTolerate0 .Add (uint32 (time .Now ().Unix ()+ 30 ), 10 )
415
+ if len (aggMetricTolerate0 .chunks ) != 0 {
416
+ t .Fatalf ("expected to have 0 chunks in aggmetric, but there were %d" , len (aggMetricTolerate0 .chunks ))
417
+ }
418
+ if sampleTooFarAhead .Peek () != 1 {
419
+ t .Fatalf ("expected the sampleTooFarAhead count to be 1, but it was %d" , sampleTooFarAhead .Peek ())
420
+ }
421
+ if discardedSampleTooFarAhead .Peek () != 1 {
422
+ t .Fatalf ("expected the discardedSampleTooFarAhead count to be 1, but it was %d" , discardedSampleTooFarAhead .Peek ())
423
+ }
424
+
425
+ // add another datapoint with timestamp of now() to the aggmetric tolerating 0, should be accepted
426
+ discardedSampleTooFarAhead .SetUint32 (0 )
427
+ sampleTooFarAhead .SetUint32 (0 )
428
+ aggMetricTolerate0 .Add (uint32 (time .Now ().Unix ()), 10 )
429
+ if len (aggMetricTolerate0 .chunks ) != 1 {
430
+ t .Fatalf ("expected to have 1 chunk in aggmetric, but there were %d" , len (aggMetricTolerate0 .chunks ))
431
+ }
432
+ if sampleTooFarAhead .Peek () != 0 {
433
+ t .Fatalf ("expected the sampleTooFarAhead count to be 0, but it was %d" , sampleTooFarAhead .Peek ())
434
+ }
435
+ if discardedSampleTooFarAhead .Peek () != 0 {
436
+ t .Fatalf ("expected the discardedSampleTooFarAhead count to be 0, but it was %d" , discardedSampleTooFarAhead .Peek ())
437
+ }
438
+ }
439
+
337
440
func itersToPoints (iters []tsz.Iter ) []schema.Point {
338
441
var points []schema.Point
339
442
for _ , it := range iters {
0 commit comments