Alerting: Fix saving result_fingerprint in async alert state persister (#115005)

This commit is contained in:
Alexander Akhmetov
2025-12-16 18:09:32 +01:00
committed by GitHub
parent f64daba9dd
commit 81710ca1f5
3 changed files with 32 additions and 17 deletions
+6
View File
@@ -973,6 +973,12 @@ func (a AlertInstanceMutators) WithAnnotations(annotations InstanceAnnotations)
}
}
func (a AlertInstanceMutators) WithResultFingerprint(fp string) AlertInstanceMutator {
return func(i *AlertInstance) {
i.ResultFingerprint = fp
}
}
type Mutator[T any] func(*T)
// CopyNotificationSettings creates a deep copy of NotificationSettings.
@@ -364,10 +364,10 @@ func (st InstanceDBStore) insertInstancesBatch(sess *sqlstore.DBSession, batch [
query := strings.Builder{}
placeholders := make([]string, 0, len(batch))
args := make([]any, 0, len(batch)*13)
args := make([]any, 0, len(batch)*14)
query.WriteString("INSERT INTO alert_instance ")
query.WriteString("(rule_org_id, rule_uid, labels, labels_hash, current_state, current_reason, current_state_since, current_state_end, last_eval_time, fired_at, resolved_at, last_sent_at, annotations) VALUES ")
query.WriteString("(rule_org_id, rule_uid, labels, labels_hash, current_state, current_reason, current_state_since, current_state_end, last_eval_time, fired_at, resolved_at, last_sent_at, result_fingerprint, annotations) VALUES ")
for _, instance := range batch {
if err := models.ValidateAlertInstance(instance); err != nil {
@@ -387,7 +387,7 @@ func (st InstanceDBStore) insertInstancesBatch(sess *sqlstore.DBSession, batch [
continue
}
placeholders = append(placeholders, "(?,?,?,?,?,?,?,?,?,?,?,?,?)")
placeholders = append(placeholders, "(?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
args = append(args,
instance.RuleOrgID,
instance.RuleUID,
@@ -401,6 +401,7 @@ func (st InstanceDBStore) insertInstancesBatch(sess *sqlstore.DBSession, batch [
nullableTimeToUnix(instance.FiredAt),
nullableTimeToUnix(instance.ResolvedAt),
nullableTimeToUnix(instance.LastSentAt),
instance.ResultFingerprint,
annotationsJSON,
)
}
@@ -8,6 +8,8 @@ import (
"time"
"github.com/golang/snappy"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/grafana/grafana/pkg/util/testutil"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
@@ -391,27 +393,33 @@ func TestIntegrationFullSync(t *testing.T) {
t.Run("Should save all instances when batch size is bigger than 1", func(t *testing.T) {
batchSize = 2
newRuleUID := "y"
err := ng.InstanceStore.FullSync(ctx, append(instances, *models.AlertInstanceGen(models.InstanceMuts.WithOrgID(orgID), models.InstanceMuts.WithRuleUID(newRuleUID))), batchSize, nil)
testInstances := []models.AlertInstance{
*models.AlertInstanceGen(models.InstanceMuts.WithOrgID(orgID), models.InstanceMuts.WithRuleUID("batch1"), models.InstanceMuts.WithResultFingerprint("fp0")),
*models.AlertInstanceGen(models.InstanceMuts.WithOrgID(orgID), models.InstanceMuts.WithRuleUID("batch2"), models.InstanceMuts.WithResultFingerprint("fp1")),
*models.AlertInstanceGen(models.InstanceMuts.WithOrgID(orgID), models.InstanceMuts.WithRuleUID("batch3"), models.InstanceMuts.WithResultFingerprint("fp2")),
}
err := ng.InstanceStore.FullSync(ctx, testInstances, batchSize, nil)
require.NoError(t, err)
res, err := ng.InstanceStore.ListAlertInstances(ctx, &models.ListAlertInstancesQuery{
RuleOrgID: orgID,
})
require.NoError(t, err)
require.Len(t, res, len(instances)+1)
for _, ruleUID := range append(ruleUIDs, newRuleUID) {
found := false
for _, instance := range res {
if instance.RuleUID == ruleUID {
found = true
continue
}
}
if !found {
t.Errorf("Instance with RuleUID '%s' not found", ruleUID)
}
savedInstances := make([]models.AlertInstance, len(res))
for i, r := range res {
savedInstances[i] = *r
}
opts := []cmp.Option{
cmpopts.EquateApproxTime(time.Second), // we don't get the same precision back from the DB
cmpopts.EquateEmpty(),
cmpopts.SortSlices(func(a, b models.AlertInstance) bool {
return a.RuleUID < b.RuleUID
}),
}
require.Empty(t, cmp.Diff(testInstances, savedInstances, opts...))
})
t.Run("Should not fail when the instances are empty", func(t *testing.T) {