notifier: retry upon failure

pull/52/head
Quentin Machu 9 years ago
parent 3ff8bfaa93
commit 480589a83a

@ -29,6 +29,8 @@ updater:
# Use 0 to disable the updater entirely. # Use 0 to disable the updater entirely.
interval: 2h interval: 2h
notifier: notifier:
# How many attempts will the notifier do when a notifier backend fails.
attempts: 3
# Configuration for HTTP notifier # Configuration for HTTP notifier
http: http:
# Endpoint that will receive notifications with POST requests. # Endpoint that will receive notifications with POST requests.

@ -44,7 +44,8 @@ type UpdaterConfig struct {
// NotifierConfig is the configuration for the Notifier service and its registered notifiers. // NotifierConfig is the configuration for the Notifier service and its registered notifiers.
type NotifierConfig struct { type NotifierConfig struct {
Params map[string]interface{} `yaml:",inline"` Attempts int
Params map[string]interface{} `yaml:",inline"`
} }
// APIConfig is the configuration for the API service. // APIConfig is the configuration for the API service.
@ -68,6 +69,9 @@ var DefaultConfig = Config{
HealthPort: 6061, HealthPort: 6061,
Timeout: 900 * time.Second, Timeout: 900 * time.Second,
}, },
Notifier: &NotifierConfig{
Attempts: 5,
},
} }
// Load is a shortcut to open a file, read it, and generate a Config. // Load is a shortcut to open a file, read it, and generate a Config.

@ -20,6 +20,7 @@ import (
"time" "time"
"github.com/coreos/pkg/capnslog" "github.com/coreos/pkg/capnslog"
"github.com/coreos/pkg/timeutil"
"github.com/pborman/uuid" "github.com/pborman/uuid"
"github.com/coreos/clair/config" "github.com/coreos/clair/config"
@ -31,10 +32,10 @@ import (
var log = capnslog.NewPackageLogger("github.com/coreos/clair", "notifier") var log = capnslog.NewPackageLogger("github.com/coreos/clair", "notifier")
const ( const (
checkInterval = 5 * time.Minute checkInterval = 5 * time.Minute
refreshLockDuration = time.Minute * 2 refreshLockDuration = time.Minute * 2
lockDuration = time.Minute*8 + refreshLockDuration lockDuration = time.Minute*8 + refreshLockDuration
maxBackOff = 15 * time.Minute
) )
// TODO(Quentin-M): Allow registering custom notification handlers. // TODO(Quentin-M): Allow registering custom notification handlers.
@ -114,7 +115,7 @@ func Run(config *config.NotifierConfig, stopper *utils.Stopper) {
// Handle task. // Handle task.
done := make(chan bool, 1) done := make(chan bool, 1)
go func() { go func() {
if handleTask(notification) { if handleTask(notification, stopper, config.Attempts) {
database.MarkNotificationAsSent(node) database.MarkNotificationAsSent(node)
} }
database.Unlock(node, whoAmI) database.Unlock(node, whoAmI)
@ -160,7 +161,7 @@ func findTask(whoAmI string, stopper *utils.Stopper) (string, database.Notificat
} }
} }
func handleTask(notification database.Notification) bool { func handleTask(notification database.Notification, st *utils.Stopper, maxAttempts int) bool {
// Get notification content. // Get notification content.
// TODO(Quentin-M): Split big notifications. // TODO(Quentin-M): Split big notifications.
notificationContent, err := notification.GetContent() notificationContent, err := notification.GetContent()
@ -177,11 +178,34 @@ func handleTask(notification database.Notification) bool {
} }
// Send notification. // Send notification.
// TODO(Quentin-M): Backoff / MaxRetries
for notifierName, notifier := range notifiers { for notifierName, notifier := range notifiers {
if err := notifier.Send(payload); err != nil { var attempts int
var backOff time.Duration
for {
// Max attempts exceeded.
if attempts >= maxAttempts {
log.Infof("giving up on sending notification '%s' to notifier '%s': max attempts exceeded (%d)\n", notification.GetName(), notifierName, maxAttempts)
return false
}
// Backoff.
if backOff > 0 {
log.Infof("waiting %v before retrying to send notification '%s' to notifier '%s' (Attempt %d / %d)\n", backOff, notification.GetName(), notifierName, attempts+1, maxAttempts)
if !st.Sleep(backOff) {
return false
}
}
// Send using the current notifier.
if err := notifier.Send(payload); err == nil {
// Send has been successful. Go to the next one.
break
}
// Send failed; increase attempts/backoff and retry.
log.Errorf("could not send notification '%s' to notifier '%s': %s", notification.GetName(), notifierName, err) log.Errorf("could not send notification '%s' to notifier '%s': %s", notification.GetName(), notifierName, err)
return false backOff = timeutil.ExpBackoff(backOff, maxBackOff)
attempts++
} }
} }

Loading…
Cancel
Save