Integrate alert provider with notify persistence
This commit is contained in:
parent
e7d45c6a64
commit
cc5662f1e8
|
@ -42,13 +42,14 @@ func NewMemData() *MemData {
|
||||||
type memAlertIterator struct {
|
type memAlertIterator struct {
|
||||||
ch <-chan *types.Alert
|
ch <-chan *types.Alert
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ai memAlertIterator) Next() <-chan *types.Alert {
|
func (ai memAlertIterator) Next() <-chan *types.Alert {
|
||||||
return ai.ch
|
return ai.ch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ai memAlertIterator) Err() error { return nil }
|
func (ai memAlertIterator) Err() error { return ai.err }
|
||||||
func (ai memAlertIterator) Close() { close(ai.done) }
|
func (ai memAlertIterator) Close() { close(ai.done) }
|
||||||
|
|
||||||
// MemAlerts implements an Alerts provider based on in-memory data.
|
// MemAlerts implements an Alerts provider based on in-memory data.
|
||||||
|
|
|
@ -176,9 +176,6 @@ func (a *SQLAlerts) Subscribe() AlertIterator {
|
||||||
done = make(chan struct{})
|
done = make(chan struct{})
|
||||||
)
|
)
|
||||||
alerts, err := a.getPending()
|
alerts, err := a.getPending()
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
i := a.next
|
i := a.next
|
||||||
a.next++
|
a.next++
|
||||||
|
@ -207,17 +204,45 @@ func (a *SQLAlerts) Subscribe() AlertIterator {
|
||||||
return memAlertIterator{
|
return memAlertIterator{
|
||||||
ch: ch,
|
ch: ch,
|
||||||
done: done,
|
done: done,
|
||||||
|
err: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SQLAlerts) GetPending() AlertIterator {
|
func (a *SQLAlerts) GetPending() AlertIterator {
|
||||||
return nil
|
var (
|
||||||
|
ch = make(chan *types.Alert, 200)
|
||||||
|
done = make(chan struct{})
|
||||||
|
)
|
||||||
|
|
||||||
|
alerts, err := a.getPending()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(ch)
|
||||||
|
|
||||||
|
for _, a := range alerts {
|
||||||
|
select {
|
||||||
|
case ch <- a:
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return memAlertIterator{
|
||||||
|
ch: ch,
|
||||||
|
done: done,
|
||||||
|
err: err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SQLAlerts) getPending() ([]*types.Alert, error) {
|
func (a *SQLAlerts) getPending() ([]*types.Alert, error) {
|
||||||
rows, err := a.db.Query(`
|
rows, err := a.db.Query(`
|
||||||
SELECT labels, annotations, starts_at, ends_at, updated_at, timeout
|
SELECT a.labels, a.annotations, a.starts_at, a.ends_at, a.updated_at, a.timeout
|
||||||
FROM alerts
|
FROM
|
||||||
|
alerts AS a LEFT OUTER JOIN notify_info AS n
|
||||||
|
ON a.fingerprint == n.fingerprint
|
||||||
|
WHERE
|
||||||
|
NOT (n.delivered AND n.resolved)
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -267,6 +292,13 @@ func (a *SQLAlerts) Put(alerts ...*types.Alert) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The insert invariant requires that there are no two alerts with the same
|
||||||
|
// fingerprint that have overlapping activity range ([StartsAt:EndsAt]).
|
||||||
|
// Such alerts are merged into a single one with the union of both intervals
|
||||||
|
// as its new activity interval.
|
||||||
|
// The exact merge procedure is defined on the Alert structure. Here, we just
|
||||||
|
// care about finding intersecting alerts for each new inserts, deleting them
|
||||||
|
// if existant, and insert the new alert we retrieved by merging.
|
||||||
overlap, err := tx.Prepare(`
|
overlap, err := tx.Prepare(`
|
||||||
SELECT id(), annotations, starts_at, ends_at, updated_at, timeout FROM alerts
|
SELECT id(), annotations, starts_at, ends_at, updated_at, timeout FROM alerts
|
||||||
WHERE fingerprint = $1 AND $2 =< ends_at OR $3 >= starts_at
|
WHERE fingerprint = $1 AND $2 =< ends_at OR $3 >= starts_at
|
||||||
|
@ -299,7 +331,7 @@ func (a *SQLAlerts) Put(alerts ...*types.Alert) error {
|
||||||
for _, alert := range alerts {
|
for _, alert := range alerts {
|
||||||
fp := alert.Fingerprint()
|
fp := alert.Fingerprint()
|
||||||
|
|
||||||
// Retrieve all overlapping alerts and delete them.
|
// Retrieve all intersecting alerts and delete them.
|
||||||
olaps, err := overlap.Query(fp, alert.StartsAt, alert.EndsAt)
|
olaps, err := overlap.Query(fp, alert.StartsAt, alert.EndsAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
|
@ -377,6 +409,12 @@ func (a *SQLAlerts) Put(alerts ...*types.Alert) error {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.mtx.RLock()
|
||||||
|
for _, ch := range a.listeners {
|
||||||
|
ch <- alert
|
||||||
|
}
|
||||||
|
a.mtx.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
|
|
Loading…
Reference in New Issue