grafana/pkg/services/ngalert/state/historian/multiple_test.go
Alexander Weaver a31672fa40
Alerting: Create new state history "fanout" backend that dispatches to multiple other backends at once (#64774)
* Rename RecordStatesAsync to Record

* Rename QueryStates to Query

* Implement fanout writes

* Implement primary queries

* Simplify error joining

* Add test for query path

* Add tests for writes and error propagation

* Allow fanout backend to be configured

* Touch up log messages and config validation

* Consistent documentation for all backend structs

* Parse and normalize backend names more consistently against an enum

* Touch-ups to documentation

* Improve clarity around multi-record blocking

* Keep primary and secondaries more distinct

* Rename fanout backend to multiple backend

* Simplify config keys for multi backend mode
2023-03-17 12:41:18 -05:00

79 lines
2.1 KiB
Go

package historian
import (
"context"
"fmt"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/data"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/ngalert/state"
history_model "github.com/grafana/grafana/pkg/services/ngalert/state/historian/model"
"github.com/stretchr/testify/require"
)
func TestMultipleBackend(t *testing.T) {
t.Run("querying dispatches to primary", func(t *testing.T) {
one := &fakeBackend{resp: data.NewFrame("one")}
two := &fakeBackend{resp: data.NewFrame("two")}
three := &fakeBackend{resp: data.NewFrame("three")}
fan := NewMultipleBackend(one, two, three)
resp, err := fan.Query(context.Background(), ngmodels.HistoryQuery{})
require.NoError(t, err)
require.Equal(t, "one", resp.Name)
})
t.Run("writes dispatch to all", func(t *testing.T) {
one := &fakeBackend{}
two := &fakeBackend{}
three := &fakeBackend{}
fan := NewMultipleBackend(one, two, three)
rule := history_model.RuleMeta{}
vs := []state.StateTransition{{}}
err := <-fan.Record(context.Background(), rule, vs)
require.NoError(t, err)
require.NotEmpty(t, one.last)
require.NotEmpty(t, two.last)
require.NotEmpty(t, three.last)
})
t.Run("writes combine errors", func(t *testing.T) {
one := &fakeBackend{err: fmt.Errorf("error one")}
two := &fakeBackend{err: fmt.Errorf("error two")}
three := &fakeBackend{}
fan := NewMultipleBackend(one, two, three)
rule := history_model.RuleMeta{}
vs := []state.StateTransition{{}}
err := <-fan.Record(context.Background(), rule, vs)
require.Error(t, err)
require.ErrorContains(t, err, "error one")
require.ErrorContains(t, err, "error two")
})
}
type fakeBackend struct {
resp *data.Frame
err error
last []state.StateTransition
}
func (f *fakeBackend) Record(ctx context.Context, rule history_model.RuleMeta, states []state.StateTransition) <-chan error {
ch := make(chan error, 1)
if f.err != nil {
ch <- f.err
}
f.last = states
defer close(ch)
return ch
}
func (f *fakeBackend) Query(ctx context.Context, query ngmodels.HistoryQuery) (*data.Frame, error) {
return f.resp, f.err
}