services

package
v1.0.29 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2025 License: Apache-2.0 Imports: 14 Imported by: 0

README

Blog Notification Service

Overview

The notification service provides a flexible and extensible system for sending notifications in the blog application. It supports multiple notification providers and handles async processing with retry logic.

Features

  • Multiple Providers: Support for email, webhook, and custom notification providers
  • Async Processing: Non-blocking notification sending with background workers
  • Retry Logic: Automatic retry with exponential backoff for failed notifications
  • Provider Interface: Easy to extend with new notification providers
  • Test Mode: Built-in test mode for development and testing

Architecture

NotificationService
├── Provider Interface
│   ├── EmailProvider
│   ├── WebhookProvider
│   └── (Custom Providers)
├── Async Queue
├── Worker Pool
└── Retry Logic

Usage

Initialize the Service
// Create notification service with 5 workers
notificationService := services.NewNotificationService(5)

// Configure email provider
emailConfig := services.EmailConfig{
    SMTPHost:     "smtp.example.com",
    SMTPPort:     "587",
    SMTPUsername: "user@example.com",
    SMTPPassword: "password",
    FromEmail:    "noreply@example.com",
    FromName:     "Blog Notifications",
    TestMode:     false, // Set to true for testing
}
emailProvider := services.NewEmailProvider(emailConfig)
notificationService.RegisterProvider(emailProvider)

// Configure webhook provider
webhookConfig := services.WebhookConfig{
    DefaultWebhookURL: "https://api.example.com/webhooks",
    SigningSecret:     "webhook-secret",
    TestMode:          false,
}
webhookProvider := services.NewWebhookProvider(webhookConfig)
notificationService.RegisterProvider(webhookProvider)
Send Notifications
// Send comment moderation notification
err := notificationService.SendCommentModerationNotification(comment, post)

// Send comment approval notification
err := notificationService.SendCommentApprovalNotification(comment, post)

// Send custom notification
notification := &Notification{
    Type: NotificationTypeCommentReply,
    Recipient: NotificationRecipient{
        Email: "user@example.com",
        Name:  "John Doe",
    },
    Subject: "New reply to your comment",
    Content: "Someone replied to your comment...",
    Data: map[string]interface{}{
        "comment_id": "123",
        "reply_id":   "456",
    },
}
err := notificationService.Send(notification)
Environment Variables
# Email Provider Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
FROM_EMAIL=noreply@yourblog.com

# Webhook Provider Configuration
WEBHOOK_URL=https://api.yourservice.com/webhooks
WEBHOOK_SECRET=your-webhook-secret

# Test Mode (logs notifications instead of sending)
NOTIFICATION_TEST_MODE=true

Implementing a Custom Provider

To add a new notification provider, implement the NotificationProvider interface:

type NotificationProvider interface {
    Send(ctx context.Context, notification *Notification) error
    CanHandle(notification *Notification) bool
    Name() string
}

Example SMS provider:

type SMSProvider struct {
    client *sms.Client
}

func (p *SMSProvider) Send(ctx context.Context, notification *Notification) error {
    if notification.Recipient.Phone == "" {
        return fmt.Errorf("phone number required")
    }
    
    return p.client.SendSMS(
        notification.Recipient.Phone,
        notification.Content,
    )
}

func (p *SMSProvider) CanHandle(notification *Notification) bool {
    return notification.Recipient.Phone != ""
}

func (p *SMSProvider) Name() string {
    return "SMSProvider"
}

Testing

The service includes comprehensive tests and a mock provider for testing:

// Create mock provider for testing
mockProvider := NewMockProvider("test")
service.RegisterProvider(mockProvider)

// Send notification
err := service.SendCommentModerationNotification(comment, post)

// Verify notification was sent
assert.Len(t, mockProvider.sentNotifications, 1)

Retry Logic

Failed notifications are automatically retried with exponential backoff:

  • Maximum retries: 3
  • Initial backoff: 1 second
  • Backoff multiplier: 2x

Performance Considerations

  • Worker Pool Size: Adjust based on expected notification volume
  • Queue Size: Default is 1000, increase for high-volume scenarios
  • Timeout: Configure provider timeouts appropriately
  • Graceful Shutdown: Call Shutdown() to process remaining notifications

Integration Status

Completed:

  • Comment moderation notifications
  • Comment approval notifications
  • Email provider implementation
  • Webhook provider implementation
  • Async processing with retry logic
  • Comprehensive test coverage

🚧 TODO:

  • AWS SES provider
  • SMS provider (Twilio/SNS)
  • Push notification provider
  • Notification preferences per user
  • Notification templates
  • Batch notification sending

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type EmailConfig

type EmailConfig struct {
	SMTPHost     string
	SMTPPort     string
	SMTPUsername string
	SMTPPassword string
	FromEmail    string
	FromName     string
	TestMode     bool // If true, logs emails instead of sending
}

EmailConfig holds email provider configuration

type EmailProvider

type EmailProvider struct {
	// contains filtered or unexported fields
}

EmailProvider implements NotificationProvider for email notifications

func NewEmailProvider

func NewEmailProvider(config EmailConfig) *EmailProvider

NewEmailProvider creates a new email provider

func (*EmailProvider) CanHandle

func (p *EmailProvider) CanHandle(notification *Notification) bool

CanHandle checks if this provider can handle the notification

func (*EmailProvider) Name

func (p *EmailProvider) Name() string

Name returns the provider name

func (*EmailProvider) Send

func (p *EmailProvider) Send(ctx context.Context, notification *Notification) error

Send sends an email notification

type Notification

type Notification struct {
	ID          string                `json:"id"`
	Type        NotificationType      `json:"type"`
	Recipient   NotificationRecipient `json:"recipient"`
	Subject     string                `json:"subject"`
	Content     string                `json:"content"`
	Data        map[string]any        `json:"data"`
	Status      NotificationStatus    `json:"status"`
	Attempts    int                   `json:"attempts"`
	LastAttempt time.Time             `json:"last_attempt,omitempty"`
	Error       string                `json:"error,omitempty"`
	CreatedAt   time.Time             `json:"created_at"`
	SentAt      time.Time             `json:"sent_at,omitempty"`
}

Notification represents a notification to be sent

type NotificationProvider

type NotificationProvider interface {
	Send(ctx context.Context, notification *Notification) error
	CanHandle(notification *Notification) bool
	Name() string
}

NotificationProvider is the interface for notification providers

type NotificationRecipient

type NotificationRecipient struct {
	Email   string `json:"email,omitempty"`
	Webhook string `json:"webhook,omitempty"`
	UserID  string `json:"user_id,omitempty"`
	Name    string `json:"name,omitempty"`
}

NotificationRecipient represents the recipient of a notification

type NotificationService

type NotificationService struct {
	// contains filtered or unexported fields
}

NotificationService handles sending notifications

func NewNotificationService

func NewNotificationService(workers int) *NotificationService

NewNotificationService creates a new notification service

func (*NotificationService) RegisterProvider

func (s *NotificationService) RegisterProvider(provider NotificationProvider)

RegisterProvider registers a notification provider

func (*NotificationService) Send

func (s *NotificationService) Send(notification *Notification) error

Send adds a notification to the queue for async processing

func (*NotificationService) SendCommentApprovalNotification

func (s *NotificationService) SendCommentApprovalNotification(comment *models.Comment, post *models.Post) error

SendCommentApprovalNotification sends a notification to the comment author when approved

func (*NotificationService) SendCommentModerationNotification

func (s *NotificationService) SendCommentModerationNotification(comment *models.Comment, post *models.Post) error

SendCommentModerationNotification sends a notification to moderators about a new comment

func (*NotificationService) SendSync

func (s *NotificationService) SendSync(ctx context.Context, notification *Notification) error

SendSync sends a notification synchronously

func (*NotificationService) Shutdown

func (s *NotificationService) Shutdown()

Shutdown gracefully shuts down the notification service

type NotificationStatus

type NotificationStatus string

NotificationStatus represents the delivery status

const (
	NotificationStatusPending  NotificationStatus = "pending"
	NotificationStatusSent     NotificationStatus = "sent"
	NotificationStatusFailed   NotificationStatus = "failed"
	NotificationStatusRetrying NotificationStatus = "retrying"
)

type NotificationType

type NotificationType string

NotificationType represents the type of notification

const (
	NotificationTypeCommentModeration NotificationType = "comment_moderation"
	NotificationTypeCommentApproval   NotificationType = "comment_approval"
	NotificationTypeCommentReply      NotificationType = "comment_reply"
	NotificationTypeNewPost           NotificationType = "new_post"
)

type WebhookConfig

type WebhookConfig struct {
	DefaultWebhookURL string
	SigningSecret     string
	Timeout           time.Duration
	RetryAttempts     int
	TestMode          bool // If true, logs webhooks instead of sending
}

WebhookConfig holds webhook provider configuration

type WebhookPayload

type WebhookPayload struct {
	ID        string         `json:"id"`
	Type      string         `json:"type"`
	Timestamp time.Time      `json:"timestamp"`
	Data      map[string]any `json:"data"`
}

WebhookPayload represents the webhook payload structure

type WebhookProvider

type WebhookProvider struct {
	// contains filtered or unexported fields
}

WebhookProvider implements NotificationProvider for webhook notifications

func NewWebhookProvider

func NewWebhookProvider(config WebhookConfig) *WebhookProvider

NewWebhookProvider creates a new webhook provider

func (*WebhookProvider) CanHandle

func (p *WebhookProvider) CanHandle(notification *Notification) bool

CanHandle checks if this provider can handle the notification

func (*WebhookProvider) Name

func (p *WebhookProvider) Name() string

Name returns the provider name

func (*WebhookProvider) Send

func (p *WebhookProvider) Send(ctx context.Context, notification *Notification) error

Send sends a webhook notification

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL