# 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
