From b70dc3d00d2cb4543ed22686c6201a182b6a1c23 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Fri, 7 Nov 2025 08:35:00 +0000 Subject: [PATCH] Document layered retry semantics (P2 documentation) Add documentation to explain how transport-level and queue-level retries interact: - Email: MaxRetries (transport) * MaxAttempts (queue) = total SMTP attempts - Webhooks: RetryCount (transport) * MaxAttempts (queue) = total HTTP attempts - Example: 3 * 3 = 9 total delivery attempts for a single notification This clarifies the multiplicative retry behavior and helps operators understand the actual retry counts when using the persistent queue. --- internal/notifications/email_enhanced.go | 5 +++++ internal/notifications/webhook_enhanced.go | 5 +++++ 2 files changed, 10 insertions(+) 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 {