321 lines
9.6 KiB
Markdown
321 lines
9.6 KiB
Markdown
# Notifier Microservice Architecture
|
|
|
|
## Overview
|
|
|
|
The Notifier microservice is designed to provide a flexible, scalable notification delivery system that supports multiple notification channels (SMTP, Slack, Ntfy, Stdout) with both REST and gRPC APIs.
|
|
|
|
## Architecture Principles
|
|
|
|
- **Clean Architecture**: Domain-driven design with clear separation of concerns
|
|
- **Interface-based Design**: All core components use interfaces for maximum flexibility
|
|
- **Pluggable Notifiers**: Easy to add new notification providers
|
|
- **Queue Abstraction**: Supports both local and distributed queues (Kafka)
|
|
- **Configuration-driven**: Viper-based configuration with environment variable support
|
|
- **Cloud-native**: Containerized with Kubernetes support
|
|
|
|
## Core Components
|
|
|
|
### 1. Domain Layer (`internal/domain/`)
|
|
|
|
The domain layer defines the core business logic and interfaces:
|
|
|
|
#### `notification.go`
|
|
- **Notification**: Core notification entity with metadata, status tracking, and retry logic
|
|
- **Priority**: Enumeration for notification urgency (Low, Normal, High, Critical)
|
|
- **NotificationType**: Supported notification channels (Email, Slack, Ntfy, Stdout)
|
|
- **NotificationStatus**: Lifecycle states (Pending, Queued, Processing, Sent, Failed, Retrying)
|
|
- **NotificationResult**: Outcome of notification delivery attempts
|
|
- **NotificationFilter**: Query interface for retrieving notifications
|
|
|
|
#### `notifier.go`
|
|
- **Notifier**: Core interface that all notification implementations must satisfy
|
|
- **NotifierFactory**: Factory pattern for creating notifier instances
|
|
- **NotificationService**: High-level service interface for notification operations
|
|
- **NotificationStats**: Statistics and metrics about notification processing
|
|
|
|
#### `queue.go`
|
|
- **Queue**: Interface for notification queue implementations
|
|
- **QueueMessage**: Wrapper around notifications with queue-specific metadata
|
|
- **QueueConfig**: Configuration for queue implementations
|
|
- **LocalQueueConfig**: In-memory queue configuration
|
|
- **KafkaQueueConfig**: Distributed Kafka queue configuration
|
|
|
|
### 2. Queue Implementation (`internal/queue/`)
|
|
|
|
#### `local.go`
|
|
- In-memory queue implementation using Go channels
|
|
- Optional disk persistence for durability
|
|
- Thread-safe with mutex protection
|
|
- Supports enqueue, dequeue, ack, and nack operations
|
|
- Configurable buffer size and retry behavior
|
|
|
|
### 3. Notifier Implementations (`internal/notifier/`)
|
|
|
|
#### `notifier.go`
|
|
- **Factory**: Manages and creates notifier instances
|
|
- **BaseNotifier**: Common functionality shared by all notifiers
|
|
- Validation and context checking utilities
|
|
|
|
#### `stdout.go`
|
|
- Simple stdout notifier for debugging and development
|
|
- Prints notifications to console with formatted output
|
|
|
|
#### `smtp.go`
|
|
- Email notifications via SMTP
|
|
- Supports TLS/SSL
|
|
- Configurable SMTP server, port, and authentication
|
|
- RFC-compliant email message formatting
|
|
|
|
#### `ntfy.go`
|
|
- Integration with ntfy.sh push notification service
|
|
- Supports custom ntfy servers
|
|
- Priority mapping and metadata support
|
|
- Rich notification features (tags, click actions, attachments)
|
|
|
|
#### `slack.go`
|
|
- Slack webhook integration
|
|
- Channel-specific webhook support
|
|
- Rich message formatting with blocks
|
|
- Priority indicators and custom branding
|
|
|
|
### 4. Configuration (`internal/config/`)
|
|
|
|
#### `config.go`
|
|
- Viper-based configuration management
|
|
- Support for YAML config files and environment variables
|
|
- Default value handling
|
|
- Comprehensive validation
|
|
- Hierarchical configuration structure:
|
|
- Server settings (ports, host, mode)
|
|
- Queue configuration
|
|
- Notifier credentials
|
|
- Logging settings
|
|
- Metrics and observability
|
|
- Health check configuration
|
|
|
|
### 5. API Layer
|
|
|
|
#### gRPC API (`api/grpc/`)
|
|
|
|
**`notifier.proto`**
|
|
- Protocol buffer definitions for the gRPC service
|
|
- Operations:
|
|
- `SendNotification`: Send single notification
|
|
- `SendBatchNotifications`: Send multiple notifications
|
|
- `GetNotification`: Retrieve notification by ID
|
|
- `ListNotifications`: Query notifications with filters
|
|
- `CancelNotification`: Cancel pending notification
|
|
- `RetryNotification`: Retry failed notification
|
|
- `GetStats`: Retrieve service statistics
|
|
- `HealthCheck`: Service health verification
|
|
|
|
#### REST API (`api/rest/`)
|
|
|
|
**`handlers.go`**
|
|
- HTTP handlers for REST endpoints
|
|
- Request validation and error handling
|
|
- JSON serialization/deserialization
|
|
|
|
**`router.go`**
|
|
- Gorilla mux router configuration
|
|
- Middleware for logging and CORS
|
|
- Route definitions matching gRPC operations
|
|
|
|
**`types.go`**
|
|
- REST API request/response types
|
|
- Domain model conversions
|
|
- Validation logic
|
|
|
|
### 6. Entry Points (`cmd/`)
|
|
|
|
#### `grpcserver/main.go`
|
|
- Standalone gRPC server
|
|
- Service initialization and dependency injection
|
|
- Graceful shutdown handling
|
|
|
|
#### `restserver/main.go`
|
|
- Standalone REST server
|
|
- HTTP server configuration
|
|
- Graceful shutdown handling
|
|
|
|
## Data Flow
|
|
|
|
### Sending a Notification
|
|
|
|
```
|
|
Client Request (REST/gRPC)
|
|
↓
|
|
API Handler
|
|
↓
|
|
NotificationService.Send()
|
|
↓
|
|
Queue.Enqueue()
|
|
↓
|
|
[Notification queued]
|
|
↓
|
|
Worker dequeues (Queue.Dequeue())
|
|
↓
|
|
NotifierFactory.Create()
|
|
↓
|
|
Notifier.Send()
|
|
↓
|
|
Provider API (SMTP/Slack/Ntfy/Stdout)
|
|
↓
|
|
Queue.Ack() or Queue.Nack()
|
|
↓
|
|
Update notification status
|
|
↓
|
|
[Notification sent or failed]
|
|
```
|
|
|
|
## Queue Strategies
|
|
|
|
### Local Queue
|
|
- In-memory implementation using Go channels
|
|
- Fast and simple for single-instance deployments
|
|
- Optional disk persistence for durability
|
|
- Suitable for development and small-scale production
|
|
|
|
### Kafka Queue (Future)
|
|
- Distributed queue for multi-instance deployments
|
|
- Guarantees delivery across service restarts
|
|
- Horizontal scalability
|
|
- Exactly-once semantics with idempotence
|
|
- Suitable for high-throughput production environments
|
|
|
|
## Notification Lifecycle
|
|
|
|
1. **Pending**: Notification created but not yet queued
|
|
2. **Queued**: Added to queue, waiting for processing
|
|
3. **Processing**: Worker has dequeued and is sending
|
|
4. **Sent**: Successfully delivered to provider
|
|
5. **Failed**: Delivery failed after max retries
|
|
6. **Retrying**: Temporarily failed, will retry
|
|
|
|
## Retry Strategy
|
|
|
|
- Configurable max retries (default: 3)
|
|
- Pluggable backoff strategies:
|
|
- **Exponential**: 2^n delay between retries
|
|
- **Linear**: Fixed increment between retries
|
|
- **Fixed**: Constant delay between retries
|
|
|
|
## Configuration Management
|
|
|
|
### Hierarchy (highest to lowest priority)
|
|
1. Environment variables (prefixed with `NOTIFIER_`)
|
|
2. Configuration file (config.yaml)
|
|
3. Default values
|
|
|
|
### Example Environment Variables
|
|
```bash
|
|
NOTIFIER_SERVER_GRPC_PORT=50051
|
|
NOTIFIER_SERVER_REST_PORT=8080
|
|
NOTIFIER_QUEUE_TYPE=local
|
|
NOTIFIER_NOTIFIERS_SMTP_HOST=smtp.gmail.com
|
|
NOTIFIER_NOTIFIERS_SLACK_WEBHOOK_URL=https://hooks.slack.com/...
|
|
```
|
|
|
|
## Deployment Strategies
|
|
|
|
### Docker Compose
|
|
- Single-host deployment
|
|
- All components in one compose file
|
|
- Optional Kafka, Prometheus, and Grafana services
|
|
- Volume mounts for configuration and persistence
|
|
|
|
### Kubernetes
|
|
- Multi-instance deployment with HPA
|
|
- Separate services for REST and gRPC
|
|
- ConfigMaps for configuration
|
|
- Secrets for credentials
|
|
- Ingress for external access
|
|
- Health checks and readiness probes
|
|
- Resource limits and requests
|
|
|
|
### Scaling Considerations
|
|
|
|
#### Horizontal Scaling
|
|
- Multiple instances can run concurrently
|
|
- Use Kafka queue for distributed message processing
|
|
- Stateless design allows easy scaling
|
|
|
|
#### Vertical Scaling
|
|
- Increase worker count per instance
|
|
- Tune queue buffer sizes
|
|
- Adjust resource limits
|
|
|
|
## Observability
|
|
|
|
### Metrics (Prometheus)
|
|
- Total notifications sent/failed
|
|
- Notifications by type and status
|
|
- Average latency
|
|
- Queue size
|
|
- Worker utilization
|
|
|
|
### Health Checks
|
|
- Dedicated health endpoint
|
|
- Component-level health reporting
|
|
- Kubernetes liveness/readiness probes
|
|
|
|
### Logging
|
|
- Structured JSON logging
|
|
- Configurable log levels
|
|
- Request/response logging
|
|
- Error tracking
|
|
|
|
## Security
|
|
|
|
### Authentication
|
|
- API keys for REST endpoints (to be implemented)
|
|
- mTLS for gRPC (to be implemented)
|
|
- Kubernetes RBAC for service account
|
|
|
|
### Authorization
|
|
- Per-notifier credential management
|
|
- Secrets stored in Kubernetes Secrets or external secret manager
|
|
- No credentials in configuration files
|
|
|
|
### Network Security
|
|
- Non-root container user
|
|
- Read-only root filesystem where possible
|
|
- Minimal container image (Alpine-based)
|
|
- Security context restrictions
|
|
|
|
## Extension Points
|
|
|
|
### Adding a New Notifier
|
|
|
|
1. Create new file in `internal/notifier/`
|
|
2. Implement the `domain.Notifier` interface:
|
|
- `Send(ctx, notification) -> result`
|
|
- `Type() -> NotificationType`
|
|
- `Validate(notification) -> error`
|
|
- `Close() -> error`
|
|
3. Add configuration struct to `internal/config/`
|
|
4. Register in factory during initialization
|
|
5. Update protobuf and REST API types
|
|
6. Add configuration example to `config.yaml`
|
|
|
|
### Adding a New Queue Implementation
|
|
|
|
1. Create new file in `internal/queue/`
|
|
2. Implement the `domain.Queue` interface
|
|
3. Add configuration to `domain.QueueConfig`
|
|
4. Update queue factory/initialization logic
|
|
5. Add configuration example
|
|
|
|
## Next Steps for Implementation
|
|
|
|
1. **Generate Protocol Buffers**: Run `make proto-gen` to generate gRPC code
|
|
2. **Implement Service Layer**: Create the main service that ties everything together
|
|
3. **Implement Server Main Functions**: Wire up dependencies in `cmd/`
|
|
4. **Add Tests**: Unit tests for notifiers, integration tests for queue
|
|
5. **Add Kafka Queue**: Implement distributed queue using Kafka
|
|
6. **Add Metrics**: Prometheus instrumentation
|
|
7. **Add Authentication**: API key or OAuth support
|
|
8. **Add Rate Limiting**: Prevent abuse and manage provider quotas
|
|
9. **Add Notification Templates**: Support for templated messages
|
|
10. **Add Webhooks**: Allow callbacks on notification status changes
|