@@ -10,6 +10,7 @@ import (
1010 "github.com/icinga/icinga-notifications/internal/recipient"
1111 "github.com/icinga/icingadb/pkg/icingadb"
1212 "github.com/icinga/icingadb/pkg/logging"
13+ "github.com/icinga/icingadb/pkg/types"
1314 "go.uber.org/zap"
1415 "golang.org/x/sync/errgroup"
1516 "sync"
2021 currentIncidentsMu sync.Mutex
2122)
2223
24+ func LoadOpenIncidents (
25+ ctx context.Context , db * icingadb.DB , logger * logging.Logger , runtimeConfig * config.RuntimeConfig , configFile * config.ConfigFile ,
26+ ) error {
27+ var incidentRows []* IncidentRow
28+ err := db .SelectContext (ctx , & incidentRows , db .BuildSelectStmt (& IncidentRow {}, & IncidentRow {})+ ` WHERE "recovered_at" IS NULL` )
29+ if err != nil {
30+ logger .Errorw ("failed to load active incidents from database" , zap .Error (err ))
31+
32+ return errors .New ("failed to fetch open incidents" )
33+ }
34+
35+ incidents := make (map [* object.Object ]* Incident )
36+ g , childCtx := errgroup .WithContext (ctx )
37+ for _ , incidentRow := range incidentRows {
38+ incident := & Incident {
39+ db : db ,
40+ logger : logger ,
41+ runtimeConfig : runtimeConfig ,
42+ StartedAt : incidentRow .StartedAt .Time (),
43+ incidentRowID : incidentRow .ID ,
44+ configFile : configFile ,
45+ SeverityBySource : map [int64 ]event.Severity {},
46+ EscalationState : map [escalationID ]* EscalationState {},
47+ Rules : map [ruleID ]struct {}{},
48+ Recipients : map [recipient.Key ]* RecipientState {},
49+ }
50+
51+ obj , err := object .LoadFromDB (ctx , db , incidentRow .ObjectID )
52+ if err != nil {
53+ return err
54+ }
55+
56+ incident .Object = obj
57+
58+ g .Go (func () error {
59+ return incident .LoadSourceSeverities (childCtx )
60+ })
61+ g .Go (func () error {
62+ return incident .LoadEscalationsState (childCtx )
63+ })
64+ g .Go (func () error {
65+ err := incident .ReloadRecipients (childCtx )
66+ if err != nil {
67+ return err
68+ }
69+
70+ tx , err := db .BeginTxx (ctx , nil )
71+ if err != nil {
72+ return err
73+ }
74+ defer func () { _ = tx .Rollback () }()
75+
76+ _ , err = incident .evaluateRules (childCtx , tx , 0 , types.Int {})
77+ if err != nil {
78+ return err
79+ }
80+
81+ incident .evaluateEscalations ()
82+ if err = tx .Commit (); err != nil {
83+ return err
84+ }
85+
86+ return childCtx .Err ()
87+ })
88+
89+ incidents [obj ] = incident
90+ }
91+
92+ if err = g .Wait (); err != nil {
93+ return err
94+ }
95+
96+ currentIncidentsMu .Lock ()
97+ defer currentIncidentsMu .Unlock ()
98+
99+ currentIncidents = incidents
100+
101+ return nil
102+ }
103+
23104func GetCurrent (
24105 ctx context.Context , db * icingadb.DB , obj * object.Object , logger * logging.Logger , runtimeConfig * config.RuntimeConfig ,
25106 configFile * config.ConfigFile , create bool ,
@@ -54,47 +135,10 @@ func GetCurrent(
54135
55136 g , childCtx := errgroup .WithContext (ctx )
56137 g .Go (func () error {
57- sourceSeverity := & SourceSeverity {IncidentID : ir .ID }
58- var sources []SourceSeverity
59- err := db .SelectContext (
60- childCtx , & sources ,
61- db .Rebind (db .BuildSelectStmt (sourceSeverity , sourceSeverity )+ ` WHERE "incident_id" = ? AND "severity" != ?` ),
62- ir .ID , event .SeverityOK ,
63- )
64- if err != nil {
65- logger .Errorw (
66- "failed to load incident source severities from database" , zap .String ("object" , obj .DisplayName ()),
67- zap .String ("incident" , incident .String ()), zap .Error (err ),
68- )
69-
70- return errors .New ("failed to load incident source severities" )
71- }
72-
73- for _ , source := range sources {
74- incident .SeverityBySource [source .SourceID ] = source .Severity
75- }
76-
77- return childCtx .Err ()
138+ return incident .LoadSourceSeverities (childCtx )
78139 })
79-
80140 g .Go (func () error {
81- state := & EscalationState {}
82- var states []* EscalationState
83- err = db .SelectContext (childCtx , & states , db .Rebind (db .BuildSelectStmt (state , state )+ ` WHERE "incident_id" = ?` ), ir .ID )
84- if err != nil {
85- logger .Errorw (
86- "failed to load incident rule escalation states" , zap .String ("object" , obj .DisplayName ()),
87- zap .String ("incident" , incident .String ()), zap .Error (err ),
88- )
89-
90- return errors .New ("failed to load incident rule escalation states" )
91- }
92-
93- for _ , state := range states {
94- incident .EscalationState [state .RuleEscalationID ] = state
95- }
96-
97- return childCtx .Err ()
141+ return incident .LoadEscalationsState (childCtx )
98142 })
99143
100144 if err := g .Wait (); err != nil {
@@ -118,9 +162,7 @@ func GetCurrent(
118162 currentIncident .Lock ()
119163 defer currentIncident .Unlock ()
120164
121- contact := & ContactRow {}
122- var contacts []* ContactRow
123- err := db .SelectContext (ctx , & contacts , db .Rebind (db .BuildSelectStmt (contact , contact )+ ` WHERE "incident_id" = ?` ), currentIncident .ID ())
165+ err := currentIncident .ReloadRecipients (ctx )
124166 if err != nil {
125167 logger .Errorw (
126168 "failed to reload incident recipients" , zap .String ("object" , obj .DisplayName ()),
@@ -129,13 +171,6 @@ func GetCurrent(
129171
130172 return nil , false , errors .New ("failed to load incident recipients" )
131173 }
132-
133- recipients := make (map [recipient.Key ]* RecipientState )
134- for _ , contact := range contacts {
135- recipients [contact .Key ] = & RecipientState {Role : contact .Role }
136- }
137-
138- currentIncident .Recipients = recipients
139174 }
140175
141176 return currentIncident , created , nil
0 commit comments