diff --git a/internal/notifications/email_enhanced.go b/internal/notifications/email_enhanced.go index fa70a17..e5c2428 100644 --- a/internal/notifications/email_enhanced.go +++ b/internal/notifications/email_enhanced.go @@ -37,6 +37,11 @@ func NewEnhancedEmailManager(config EmailProviderConfig) *EnhancedEmailManager { } // SendEmailWithRetry sends email with retry logic +// Note: When used with the persistent queue, retry behavior is layered: +// - Transport retries (this function): up to MaxRetries attempts with RetryDelay between +// - Queue retries: up to MaxAttempts (default 3) with exponential backoff +// Total attempts = MaxRetries * MaxAttempts (e.g., 3 * 3 = 9 SMTP calls for a single notification) +// This ensures delivery even during transient failures at either layer. func (e *EnhancedEmailManager) SendEmailWithRetry(subject, htmlBody, textBody string) error { var lastErr error diff --git a/internal/notifications/webhook_enhanced.go b/internal/notifications/webhook_enhanced.go index 0f3dbff..60f43ea 100644 --- a/internal/notifications/webhook_enhanced.go +++ b/internal/notifications/webhook_enhanced.go @@ -194,6 +194,11 @@ func (n *NotificationManager) shouldSendWebhook(webhook EnhancedWebhookConfig, a } // sendWebhookWithRetry implements exponential backoff retry with enhanced error tracking +// Note: When used with the persistent queue, retry behavior is layered: +// - Transport retries (this function): up to RetryCount attempts with exponential backoff +// - Queue retries: up to MaxAttempts (default 3) with exponential backoff +// Total attempts = RetryCount * MaxAttempts (e.g., 3 * 3 = 9 HTTP calls for a single notification) +// This ensures delivery even during transient failures at either layer. func (n *NotificationManager) sendWebhookWithRetry(webhook EnhancedWebhookConfig, payload []byte) error { maxRetries := webhook.RetryCount if maxRetries <= 0 {