[v11.0.x] Alerting: Fix scheduler to sort rules before evaluation (#88021)
* Alerting: Fix scheduler to sort rules before evaluation (#88006)
sort rules scheduled for evaluation to make sure that the order is stable between evaluations.
This is especially important in HA mode.
(cherry picked from commit 05d6813a09)
* use old generators
---------
Co-authored-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
co-authored by
Yuri Tseretyan
parent
f622370b7a
commit
152cce216a
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/benbjohnson/clock"
|
||||
@@ -325,6 +327,9 @@ func (sch *schedule) processTick(ctx context.Context, dispatcherGroup *errgroup.
|
||||
step = sch.baseInterval.Nanoseconds() / int64(len(readyToRun))
|
||||
}
|
||||
|
||||
slices.SortFunc(readyToRun, func(a, b readyToRunItem) int {
|
||||
return strings.Compare(a.rule.UID, b.rule.UID)
|
||||
})
|
||||
for i := range readyToRun {
|
||||
item := readyToRun[i]
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -354,6 +355,47 @@ func TestProcessTicks(t *testing.T) {
|
||||
require.Len(t, updated, 1)
|
||||
require.Equal(t, expectedUpdated, updated[0])
|
||||
})
|
||||
t.Run("on 12th tick all rules should be stopped", func(t *testing.T) {
|
||||
expectedToBeStopped, err := ruleStore.GetAlertRulesKeysForScheduling(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
ruleStore.rules = map[string]*models.AlertRule{}
|
||||
tick = tick.Add(cfg.BaseInterval)
|
||||
scheduled, stopped, updated := sched.processTick(ctx, dispatcherGroup, tick)
|
||||
|
||||
require.Emptyf(t, scheduled, "None rules should be scheduled")
|
||||
|
||||
require.Len(t, stopped, len(expectedToBeStopped))
|
||||
|
||||
require.Emptyf(t, updated, "No rules should be updated")
|
||||
})
|
||||
|
||||
t.Run("scheduled rules should be sorted", func(t *testing.T) {
|
||||
rules := models.GenerateAlertRules(rand.Intn(10)+10, models.AlertRuleGen(models.WithOrgID(mainOrgID), models.WithInterval(cfg.BaseInterval)))
|
||||
ruleStore.rules = map[string]*models.AlertRule{}
|
||||
ruleStore.PutRule(context.Background(), rules...)
|
||||
|
||||
expectedUids := make([]string, 0, len(rules))
|
||||
for _, rule := range rules {
|
||||
expectedUids = append(expectedUids, rule.UID)
|
||||
}
|
||||
slices.Sort(expectedUids)
|
||||
|
||||
tick = tick.Add(cfg.BaseInterval)
|
||||
|
||||
scheduled, stopped, updated := sched.processTick(ctx, dispatcherGroup, tick)
|
||||
require.Emptyf(t, stopped, "None rules are expected to be stopped")
|
||||
require.Emptyf(t, updated, "None rules are expected to be updated")
|
||||
|
||||
actualUids := make([]string, 0, len(scheduled))
|
||||
for _, rule := range scheduled {
|
||||
actualUids = append(actualUids, rule.rule.UID)
|
||||
}
|
||||
|
||||
require.Len(t, scheduled, len(rules))
|
||||
assert.Truef(t, slices.IsSorted(actualUids), "The scheduler rules should be sorted by UID but they aren't")
|
||||
require.Equal(t, expectedUids, actualUids)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSchedule_deleteAlertRule(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user