Alerting: Fix evaluation timeout (#61303)

This commit is contained in:
Yuri Tseretyan 2023-01-11 10:52:54 -05:00 committed by GitHub
parent 1a9b6873e6
commit b4e1e1871f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 2 deletions

View File

@ -41,9 +41,13 @@ type ConditionEvaluator interface {
Evaluate(ctx context.Context, now time.Time) (Results, error)
}
type expressionService interface {
ExecutePipeline(ctx context.Context, now time.Time, pipeline expr.DataPipeline) (*backend.QueryDataResponse, error)
}
type conditionEvaluator struct {
pipeline expr.DataPipeline
expressionService *expr.Service
expressionService expressionService
condition models.Condition
evalTimeout time.Duration
}
@ -62,7 +66,7 @@ func (r *conditionEvaluator) EvaluateRaw(ctx context.Context, now time.Time) (re
}()
execCtx := ctx
if r.evalTimeout <= 0 {
if r.evalTimeout >= 0 {
timeoutCtx, cancel := context.WithTimeout(ctx, r.evalTimeout)
defer cancel()
execCtx = timeoutCtx

View File

@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/stretchr/testify/require"
ptr "github.com/xorcare/pointer"
@ -544,3 +545,38 @@ func TestValidate(t *testing.T) {
})
}
}
func TestEvaluateRaw(t *testing.T) {
t.Run("should timeout if request takes too long", func(t *testing.T) {
unexpectedResponse := &backend.QueryDataResponse{}
e := conditionEvaluator{
pipeline: nil,
expressionService: &fakeExpressionService{
hook: func(ctx context.Context, now time.Time, pipeline expr.DataPipeline) (*backend.QueryDataResponse, error) {
ts := time.Now()
for time.Since(ts) <= 10*time.Second {
if ctx.Err() != nil {
return nil, ctx.Err()
}
time.Sleep(10 * time.Millisecond)
}
return unexpectedResponse, nil
},
},
condition: models.Condition{},
evalTimeout: 10 * time.Millisecond,
}
_, err := e.EvaluateRaw(context.Background(), time.Now())
require.ErrorIs(t, err, context.DeadlineExceeded)
})
}
type fakeExpressionService struct {
hook func(ctx context.Context, now time.Time, pipeline expr.DataPipeline) (*backend.QueryDataResponse, error)
}
func (f fakeExpressionService) ExecutePipeline(ctx context.Context, now time.Time, pipeline expr.DataPipeline) (*backend.QueryDataResponse, error) {
return f.hook(ctx, now, pipeline)
}