Skip to content

Commit 7b723ba

Browse files
committed
add context to Groups to allow timeouts
1 parent 82e52aa commit 7b723ba

File tree

5 files changed

+30
-10
lines changed

5 files changed

+30
-10
lines changed

api/api.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package api
1515

1616
import (
17+
"context"
1718
"errors"
1819
"fmt"
1920
"log/slog"
@@ -83,7 +84,7 @@ type Options struct {
8384
// GroupFunc returns a list of alert groups. The alerts are grouped
8485
// according to the current active configuration. Alerts returned are
8586
// filtered by the arguments provided to the function.
86-
GroupFunc func(func(*dispatch.Route) bool, func(*types.Alert, time.Time) bool) (dispatch.AlertGroups, map[model.Fingerprint][]string)
87+
GroupFunc func(context.Context, func(*dispatch.Route) bool, func(*types.Alert, time.Time) bool) (dispatch.AlertGroups, map[model.Fingerprint][]string, error)
8788
}
8889

8990
func (o Options) validate() error {

api/v2/api.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package v2
1515

1616
import (
17+
"context"
1718
"errors"
1819
"fmt"
1920
"log/slog"
@@ -77,7 +78,7 @@ type API struct {
7778
}
7879

7980
type (
80-
groupsFn func(func(*dispatch.Route) bool, func(*types.Alert, time.Time) bool) (dispatch.AlertGroups, map[prometheus_model.Fingerprint][]string)
81+
groupsFn func(context.Context, func(*dispatch.Route) bool, func(*types.Alert, time.Time) bool) (dispatch.AlertGroups, map[prometheus_model.Fingerprint][]string, error)
8182
groupMutedFunc func(routeID, groupKey string) ([]string, bool)
8283
getAlertStatusFn func(prometheus_model.Fingerprint) types.AlertStatus
8384
setAlertStatusFn func(prometheus_model.LabelSet)
@@ -405,7 +406,10 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams
405406
}(receiverFilter)
406407

407408
af := api.alertFilter(matchers, *params.Silenced, *params.Inhibited, *params.Active)
408-
alertGroups, allReceivers := api.alertGroups(rf, af)
409+
alertGroups, allReceivers, err := api.alertGroups(params.HTTPRequest.Context(), rf, af)
410+
if err != nil {
411+
return alertgroup_ops.NewGetAlertGroupsInternalServerError()
412+
}
409413

410414
res := make(open_api_models.AlertGroups, 0, len(alertGroups))
411415

cmd/alertmanager/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,8 @@ func run() int {
351351
disp.Stop()
352352
}()
353353

354-
groupFn := func(routeFilter func(*dispatch.Route) bool, alertFilter func(*types.Alert, time.Time) bool) (dispatch.AlertGroups, map[model.Fingerprint][]string) {
355-
return disp.Groups(routeFilter, alertFilter)
354+
groupFn := func(ctx context.Context, routeFilter func(*dispatch.Route) bool, alertFilter func(*types.Alert, time.Time) bool) (dispatch.AlertGroups, map[model.Fingerprint][]string, error) {
355+
return disp.Groups(ctx, routeFilter, alertFilter)
356356
}
357357

358358
// An interface value that holds a nil concrete value is non-nil.

dispatch/dispatch.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ func (d *Dispatcher) WaitForLoading() {
216216
d.loadingFinished.Wait()
217217
}
218218

219+
func (d *Dispatcher) LoadingDone() <-chan struct{} {
220+
doneChan := make(chan struct{})
221+
go func() {
222+
d.WaitForLoading()
223+
close(doneChan)
224+
}()
225+
226+
return doneChan
227+
}
228+
219229
// AlertGroup represents how alerts exist within an aggrGroup.
220230
type AlertGroup struct {
221231
Alerts types.AlertSlice
@@ -237,7 +247,12 @@ func (ag AlertGroups) Less(i, j int) bool {
237247
func (ag AlertGroups) Len() int { return len(ag) }
238248

239249
// Groups returns a slice of AlertGroups from the dispatcher's internal state.
240-
func (d *Dispatcher) Groups(routeFilter func(*Route) bool, alertFilter func(*types.Alert, time.Time) bool) (AlertGroups, map[model.Fingerprint][]string) {
250+
func (d *Dispatcher) Groups(ctx context.Context, routeFilter func(*Route) bool, alertFilter func(*types.Alert, time.Time) bool) (AlertGroups, map[model.Fingerprint][]string, error) {
251+
select {
252+
case <-ctx.Done():
253+
return nil, nil, ctx.Err()
254+
case <-d.LoadingDone():
255+
}
241256
d.WaitForLoading()
242257
groups := AlertGroups{}
243258

@@ -300,7 +315,7 @@ func (d *Dispatcher) Groups(routeFilter func(*Route) bool, alertFilter func(*typ
300315
sort.Strings(receivers[i])
301316
}
302317

303-
return groups, receivers
318+
return groups, receivers, nil
304319
}
305320

306321
// Stop the dispatcher.

dispatch/dispatch_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ route:
428428
}
429429
require.Len(t, recorder.Alerts(), 7)
430430

431-
alertGroups, receivers := dispatcher.Groups(
431+
alertGroups, receivers, _ := dispatcher.Groups(context.Background(),
432432
func(*Route) bool {
433433
return true
434434
}, func(*types.Alert, time.Time) bool {
@@ -587,7 +587,7 @@ route:
587587
routeFilter := func(*Route) bool { return true }
588588
alertFilter := func(*types.Alert, time.Time) bool { return true }
589589

590-
alertGroups, _ := dispatcher.Groups(routeFilter, alertFilter)
590+
alertGroups, _, _ := dispatcher.Groups(context.Background(), routeFilter, alertFilter)
591591
require.Len(t, alertGroups, 6)
592592

593593
require.Equal(t, 0.0, testutil.ToFloat64(m.aggrGroupLimitReached))
@@ -605,7 +605,7 @@ route:
605605
require.Equal(t, 1.0, testutil.ToFloat64(m.aggrGroupLimitReached))
606606

607607
// Verify there are still only 6 groups.
608-
alertGroups, _ = dispatcher.Groups(routeFilter, alertFilter)
608+
alertGroups, _, _ = dispatcher.Groups(context.Background(), routeFilter, alertFilter)
609609
require.Len(t, alertGroups, 6)
610610
}
611611

0 commit comments

Comments
 (0)