345 lines
12 KiB
Markdown
345 lines
12 KiB
Markdown
# Notifier Service Client Integration Prompt
|
|
|
|
**Use this prompt with Claude or another AI assistant when building a client application that integrates with the Notifier service.**
|
|
|
|
---
|
|
|
|
## Prompt for AI Assistant
|
|
|
|
I need to build a client application that integrates with a notification service using gRPC. Please help me implement a production-ready client that follows best practices for performance, security, and reliability.
|
|
|
|
### Service Details
|
|
|
|
**Protocol:** gRPC (HTTP/2)
|
|
**Service Address:** `notifier-grpc:50051` (Kubernetes internal DNS)
|
|
**Authentication:** API Key via gRPC metadata
|
|
**API Key Format:** `nk_` prefix followed by 64 hex characters (e.g., `nk_abc123...`)
|
|
|
|
### Authentication Requirements
|
|
|
|
1. **API Key Delivery:**
|
|
- Send API key in gRPC metadata with EVERY request
|
|
- Two accepted header formats:
|
|
- `authorization: Bearer nk_your_api_key_here` (preferred)
|
|
- `x-api-key: nk_your_api_key_here`
|
|
|
|
2. **Per-Request Authentication:**
|
|
- The service validates the API key on every RPC call
|
|
- Authentication is NOT done at connection time
|
|
- This means you can (and should) use long-lived connections
|
|
|
|
3. **Rate Limiting:**
|
|
- Rate limits are enforced per API key
|
|
- Default: 100 requests per minute (configurable per key)
|
|
- Rate limit exceeded returns: `codes.ResourceExhausted`
|
|
- Implement exponential backoff retry for rate limit errors
|
|
|
|
4. **Credential Management:**
|
|
- Load API key from environment variable: `NOTIFIER_API_KEY`
|
|
- NEVER hardcode API keys in source code
|
|
- NEVER log the full API key (mask it: `nk_abc...xyz`)
|
|
- Store in Kubernetes Secret if deploying to k8s
|
|
|
|
### Connection Management Requirements
|
|
|
|
**CRITICAL:** Use long-lived gRPC connections for optimal performance.
|
|
|
|
1. **Connection Lifecycle:**
|
|
- Create ONE connection at application startup
|
|
- Reuse the connection for ALL requests
|
|
- Close the connection only when application exits
|
|
- Do NOT create a new connection for each request
|
|
|
|
2. **Keepalive Configuration:**
|
|
- Configure client keepalive to prevent connection timeouts
|
|
- Recommended settings:
|
|
- Time: 10 seconds (ping every 10s of inactivity)
|
|
- Timeout: 3 seconds (wait for ping response)
|
|
- PermitWithoutStream: true (allow pings when idle)
|
|
|
|
3. **Why This Matters:**
|
|
- Connection reuse: 10x faster (1.5ms vs 15ms per request)
|
|
- Eliminates TCP + TLS handshake overhead (10-15ms per request)
|
|
- HTTP/2 multiplexing: handle multiple concurrent requests on one connection
|
|
- Lower resource usage: one connection vs thousands
|
|
|
|
### Error Handling Requirements
|
|
|
|
1. **Handle These Error Codes:**
|
|
- `codes.Unauthenticated` - Invalid or missing API key → Log error, don't retry
|
|
- `codes.ResourceExhausted` - Rate limit exceeded → Retry with exponential backoff
|
|
- `codes.InvalidArgument` - Bad request payload → Log error, don't retry
|
|
- `codes.Unavailable` - Service temporarily unavailable → Retry with backoff
|
|
- `codes.DeadlineExceeded` - Request timeout → Retry (may be transient)
|
|
|
|
2. **Retry Strategy:**
|
|
- Implement exponential backoff: 100ms, 200ms, 400ms, 800ms
|
|
- Maximum 3-5 retry attempts for retryable errors
|
|
- Only retry: rate limits, unavailable, deadline exceeded
|
|
- Do NOT retry: authentication errors, invalid arguments
|
|
|
|
3. **Context Timeouts:**
|
|
- Set reasonable timeout for each request (5-30 seconds)
|
|
- Use `context.WithTimeout()` for every RPC call
|
|
- Allow timeout to be configurable
|
|
|
|
### Code Structure Requirements
|
|
|
|
1. **Client Structure:**
|
|
```
|
|
NotifierClient struct:
|
|
- conn: *grpc.ClientConn (long-lived)
|
|
- client: pb.NotifierServiceClient
|
|
- apiKey: string (loaded from env)
|
|
- logger: logging interface
|
|
```
|
|
|
|
2. **Required Methods:**
|
|
- `NewNotifierClient(address, apiKey string) (*NotifierClient, error)` - Initialize
|
|
- `SendNotification(ctx, request) (response, error)` - Send single notification
|
|
- `SendBatchNotifications(ctx, requests) (responses, error)` - Send batch
|
|
- `HealthCheck(ctx) error` - Verify connection health
|
|
- `Close() error` - Clean up connection
|
|
|
|
3. **Initialization Pattern:**
|
|
- Create client as singleton at application startup
|
|
- Use `sync.Once` to ensure only one instance
|
|
- Defer `Close()` in main() to ensure cleanup
|
|
|
|
### Observability Requirements
|
|
|
|
1. **Logging:**
|
|
- Log connection establishment (info level)
|
|
- Log authentication failures (warn level)
|
|
- Log rate limit exceeded (warn level)
|
|
- Log successful sends (debug level)
|
|
- NEVER log the full API key (mask it)
|
|
|
|
2. **Metrics (if using Prometheus):**
|
|
- Counter: `notifier_requests_total` (labels: status, method)
|
|
- Counter: `notifier_requests_failed_total` (labels: error_code)
|
|
- Histogram: `notifier_request_duration_seconds`
|
|
- Counter: `notifier_rate_limit_errors_total`
|
|
|
|
3. **Health Checks:**
|
|
- Implement background health check goroutine
|
|
- Check every 30-60 seconds
|
|
- Call the service's HealthCheck RPC
|
|
- Log warnings if health checks fail
|
|
|
|
### Security Requirements
|
|
|
|
1. **Credential Security:**
|
|
- Load API key ONLY from environment variables
|
|
- Never commit API keys to version control
|
|
- Use `.gitignore` to exclude any files with credentials
|
|
- Implement a `String()` method that masks the API key for logging
|
|
|
|
2. **TLS Configuration:**
|
|
- For local development: `grpc.WithInsecure()` is acceptable
|
|
- For production: Use TLS with proper certificate validation
|
|
- For Kubernetes: Internal communication may use insecure (cluster network is trusted)
|
|
|
|
3. **Graceful Degradation:**
|
|
- If notifier service is unavailable, application should continue
|
|
- Log notification failures but don't crash the application
|
|
- Consider implementing a circuit breaker pattern for resilience
|
|
|
|
### Testing Requirements
|
|
|
|
1. **Unit Tests:**
|
|
- Mock the gRPC client interface
|
|
- Test retry logic with rate limit errors
|
|
- Test context timeout handling
|
|
- Test credential masking in logs
|
|
|
|
2. **Integration Tests:**
|
|
- Test actual connection to notifier service (if available)
|
|
- Test authentication with valid and invalid keys
|
|
- Test rate limiting behavior
|
|
|
|
### Kubernetes Deployment Requirements (if applicable)
|
|
|
|
1. **Environment Variables:**
|
|
```yaml
|
|
env:
|
|
- name: NOTIFIER_API_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: notifier-credentials
|
|
key: api-key
|
|
- name: NOTIFIER_ADDRESS
|
|
value: "notifier-grpc:50051"
|
|
```
|
|
|
|
2. **Secrets Configuration:**
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: notifier-credentials
|
|
type: Opaque
|
|
stringData:
|
|
api-key: nk_your_actual_api_key_here
|
|
```
|
|
|
|
### Available gRPC Methods
|
|
|
|
The NotifierService provides these RPC methods:
|
|
|
|
1. **SendNotification** - Send a single notification
|
|
- Request: `SendNotificationRequest`
|
|
- Response: `SendNotificationResponse` (contains notification_id)
|
|
|
|
2. **SendBatchNotifications** - Send multiple notifications at once
|
|
- Request: `SendBatchNotificationsRequest`
|
|
- Response: `SendBatchNotificationsResponse` (contains notification_ids)
|
|
|
|
3. **GetNotification** - Retrieve notification status by ID
|
|
- Request: `GetNotificationRequest` (notification_id)
|
|
- Response: `GetNotificationResponse`
|
|
|
|
4. **ListNotifications** - List recent notifications
|
|
- Request: `ListNotificationsRequest` (pagination)
|
|
- Response: `ListNotificationsResponse`
|
|
|
|
5. **CancelNotification** - Cancel a pending notification
|
|
- Request: `CancelNotificationRequest` (notification_id)
|
|
- Response: `CancelNotificationResponse`
|
|
|
|
6. **RetryNotification** - Retry a failed notification
|
|
- Request: `RetryNotificationRequest` (notification_id)
|
|
- Response: `RetryNotificationResponse`
|
|
|
|
7. **GetStats** - Get service statistics
|
|
- Request: `GetStatsRequest`
|
|
- Response: `GetStatsResponse`
|
|
|
|
8. **GetNotifiers** - List available notifier types and accounts
|
|
- Request: `GetNotifiersRequest`
|
|
- Response: `GetNotifiersResponse`
|
|
|
|
9. **HealthCheck** - Verify service health
|
|
- Request: `HealthCheckRequest`
|
|
- Response: `HealthCheckResponse`
|
|
|
|
### Notification Types Supported
|
|
|
|
- `NOTIFICATION_TYPE_EMAIL` - Email notifications
|
|
- `NOTIFICATION_TYPE_SLACK` - Slack messages
|
|
- `NOTIFICATION_TYPE_NTFY` - Ntfy.sh push notifications
|
|
- `NOTIFICATION_TYPE_STDOUT` - Console output (development only)
|
|
|
|
### Request Example Structure
|
|
|
|
```protobuf
|
|
message SendNotificationRequest {
|
|
NotificationType type = 1; // Required: email, slack, ntfy, stdout
|
|
string subject = 2; // Required: notification subject/title
|
|
string body = 3; // Required: notification body/content
|
|
repeated string recipients = 4; // Required: email addresses, slack channels, etc.
|
|
Priority priority = 5; // Optional: normal, high, critical
|
|
string account = 6; // Optional: specific notifier account to use
|
|
map<string, string> metadata = 7; // Optional: additional metadata
|
|
}
|
|
```
|
|
|
|
### Implementation Goals
|
|
|
|
Please implement a client that:
|
|
|
|
1. ✅ Uses a single long-lived gRPC connection
|
|
2. ✅ Sends API key in metadata with every request
|
|
3. ✅ Implements exponential backoff retry for rate limits
|
|
4. ✅ Loads credentials from environment variables
|
|
5. ✅ Uses context with timeout for all requests
|
|
6. ✅ Implements keepalive to prevent connection timeouts
|
|
7. ✅ Includes proper error handling for all error codes
|
|
8. ✅ Logs important events without exposing credentials
|
|
9. ✅ Provides a health check mechanism
|
|
10. ✅ Includes graceful shutdown (connection cleanup)
|
|
11. ✅ Is production-ready with proper error handling and logging
|
|
12. ✅ Includes basic unit tests
|
|
|
|
### Example Usage Pattern
|
|
|
|
The client should be usable like this:
|
|
|
|
```go
|
|
// Initialize once at startup
|
|
client, err := notifier.NewClient(
|
|
os.Getenv("NOTIFIER_ADDRESS"),
|
|
os.Getenv("NOTIFIER_API_KEY"),
|
|
)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer client.Close()
|
|
|
|
// Use throughout application lifetime
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
resp, err := client.SendNotification(ctx, ¬ifier.SendRequest{
|
|
Type: notifier.TypeEmail,
|
|
Subject: "Important Alert",
|
|
Body: "This is a critical notification",
|
|
Recipients: []string{"admin@example.com"},
|
|
Priority: notifier.PriorityHigh,
|
|
})
|
|
|
|
if err != nil {
|
|
log.Printf("Failed to send notification: %v", err)
|
|
// Application continues - notification failure is not fatal
|
|
return
|
|
}
|
|
|
|
log.Printf("Notification sent successfully: %s", resp.NotificationID)
|
|
```
|
|
|
|
### Additional Context
|
|
|
|
- This is a microservices architecture running in Kubernetes
|
|
- The notifier service handles routing to multiple notification backends (SMTP, Slack, Ntfy)
|
|
- The client may need to send notifications from multiple goroutines concurrently
|
|
- High reliability is important, but notification failures should not crash the application
|
|
- The API key has a rate limit of 100 requests per minute (may vary per key)
|
|
|
|
### Code Generation Note
|
|
|
|
If you need the protobuf definitions, they can be generated from the service's proto files located at `api/grpc/proto/notifier.proto` in the notifier service repository.
|
|
|
|
---
|
|
|
|
## Usage Instructions
|
|
|
|
**Copy the prompt above and provide it to your AI assistant when building the client. The prompt includes:**
|
|
|
|
- All authentication requirements and formats
|
|
- Connection management best practices
|
|
- Error handling strategies
|
|
- Security requirements
|
|
- Observability guidelines
|
|
- Complete API method listing
|
|
- Production-ready patterns
|
|
- Kubernetes deployment configuration
|
|
|
|
**The AI assistant should generate:**
|
|
- Complete, production-ready client code
|
|
- Proper connection pooling and keepalive
|
|
- Comprehensive error handling
|
|
- Secure credential management
|
|
- Health check implementation
|
|
- Unit tests
|
|
- Usage documentation
|
|
|
|
**Review the generated code for:**
|
|
- ✅ Single long-lived connection (not creating connections per request)
|
|
- ✅ API key sent in metadata with every RPC
|
|
- ✅ Keepalive configuration present
|
|
- ✅ Exponential backoff retry logic
|
|
- ✅ No hardcoded credentials
|
|
- ✅ Proper context timeouts
|
|
- ✅ Error handling for all gRPC error codes
|
|
- ✅ Graceful shutdown (Close() method)
|