@@ -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+ runtimeConfig : runtimeConfig ,
41+ StartedAt : incidentRow .StartedAt .Time (),
42+ incidentRowID : incidentRow .ID ,
43+ configFile : configFile ,
44+ SeverityBySource : map [int64 ]event.Severity {},
45+ EscalationState : map [escalationID ]* EscalationState {},
46+ Rules : map [ruleID ]struct {}{},
47+ Recipients : map [recipient.Key ]* RecipientState {},
48+ }
49+
50+ obj , err := object .LoadFromDB (ctx , db , incidentRow .ObjectID )
51+ if err != nil {
52+ return err
53+ }
54+
55+ incident .Object = obj
56+ incident .logger = logger .With (zap .String ("object" , obj .DisplayName ()), zap .String ("incident" , incident .String ()))
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 ,
@@ -55,41 +136,10 @@ func GetCurrent(
55136
56137 g , childCtx := errgroup .WithContext (ctx )
57138 g .Go (func () error {
58- sourceSeverity := & SourceSeverity {IncidentID : ir .ID }
59- var sources []SourceSeverity
60- err := db .SelectContext (
61- childCtx , & sources ,
62- db .Rebind (db .BuildSelectStmt (sourceSeverity , sourceSeverity )+ ` WHERE "incident_id" = ? AND "severity" != ?` ),
63- ir .ID , event .SeverityOK ,
64- )
65- if err != nil {
66- incident .logger .Errorw ("Failed to load incident source severities from database" , zap .Error (err ))
67-
68- return errors .New ("failed to load incident source severities" )
69- }
70-
71- for _ , source := range sources {
72- incident .SeverityBySource [source .SourceID ] = source .Severity
73- }
74-
75- return childCtx .Err ()
139+ return incident .LoadSourceSeverities (childCtx )
76140 })
77-
78141 g .Go (func () error {
79- state := & EscalationState {}
80- var states []* EscalationState
81- err = db .SelectContext (childCtx , & states , db .Rebind (db .BuildSelectStmt (state , state )+ ` WHERE "incident_id" = ?` ), ir .ID )
82- if err != nil {
83- incident .logger .Errorw ("Failed to load incident rule escalation states" , zap .Error (err ))
84-
85- return errors .New ("failed to load incident rule escalation states" )
86- }
87-
88- for _ , state := range states {
89- incident .EscalationState [state .RuleEscalationID ] = state
90- }
91-
92- return childCtx .Err ()
142+ return incident .LoadEscalationsState (childCtx )
93143 })
94144
95145 if err := g .Wait (); err != nil {
@@ -113,21 +163,12 @@ func GetCurrent(
113163 currentIncident .Lock ()
114164 defer currentIncident .Unlock ()
115165
116- contact := & ContactRow {}
117- var contacts []* ContactRow
118- err := db .SelectContext (ctx , & contacts , db .Rebind (db .BuildSelectStmt (contact , contact )+ ` WHERE "incident_id" = ?` ), currentIncident .ID ())
166+ err := currentIncident .ReloadRecipients (ctx )
119167 if err != nil {
120168 currentIncident .logger .Errorw ("Failed to reload incident recipients" , zap .Error (err ))
121169
122170 return nil , false , errors .New ("failed to load incident recipients" )
123171 }
124-
125- recipients := make (map [recipient.Key ]* RecipientState )
126- for _ , contact := range contacts {
127- recipients [contact .Key ] = & RecipientState {Role : contact .Role }
128- }
129-
130- currentIncident .Recipients = recipients
131172 }
132173
133174 return currentIncident , created , nil
0 commit comments