This commit is contained in:
parent
9cc568e06f
commit
d2586defda
135
README.md
135
README.md
@ -2,37 +2,138 @@
|
|||||||
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
This part of the backend handles device push notifications for registered users. It consumes messages from RabbitMQ, looks up user device tokens from a MySQL database, and sends notifications via Expo's API. Failed deliveries are retried or sent to a dead-letter queue.
|
|
||||||
|
This service consumes messages from RabbitMQ, retrieves encrypted push tokens from a MySQL database, decrypts them, and sends notifications via the Expo Push API. It includes comprehensive error handling, automatic retries, dead-letter queuing, and Prometheus metrics.
|
||||||
|
|
||||||
|
|
||||||
## Requirements
|
## Features
|
||||||
- Python 3.12+
|
|
||||||
- MySQL database
|
- **Asynchronous Architecture**: Built with `asyncio`, `aio_pika`, and `aiomysql` for high-performance concurrent operations
|
||||||
- RabbitMQ
|
- **Automatic Retry Logic**: Failed notifications are automatically retried up to 5 times with exponential backoff
|
||||||
- Python packages from requirements.txt
|
- **Dead Letter Queue (DLQ)**: Messages that exceed retry limits are moved to a DLQ for manual inspection
|
||||||
|
- **Health Monitoring**: Database connection pool health checks every 60 seconds
|
||||||
|
- **Prometheus Metrics**: Real-time monitoring of queue depths and message processing stats
|
||||||
|
- **Token Management**: Automatically expires invalid or unregistered device tokens
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
RabbitMQ → Consumer → Database Lookup → Token Decryption → Expo Push API
|
||||||
|
↓ ↓
|
||||||
|
Retry Queue ←─────────── Delivery Validation ──────┘
|
||||||
|
↓
|
||||||
|
Dead Letter Queue
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Python 3.10+
|
||||||
|
- MySQL/MariaDB database
|
||||||
|
- RabbitMQ server
|
||||||
|
- Expo Push Notification service account
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running the Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python rabbitmq_handler.py
|
||||||
|
```
|
||||||
|
|
||||||
|
The service will:
|
||||||
|
1. Connect to the MySQL database
|
||||||
|
2. Establish RabbitMQ connection and declare queues
|
||||||
|
3. Start consuming messages
|
||||||
|
4. Begin Prometheus metrics server on port 9000
|
||||||
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
**Environment variables:**
|
### Database Manager (`db.py`)
|
||||||
|
|
||||||
- `LOG_LEVEL` (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
- **Pool Size**: 5 connections (configurable)
|
||||||
|
- **Health Check Interval**: 60 seconds
|
||||||
|
- **Auto-commit**: Enabled
|
||||||
|
- **Cursor Type**: DictCursor for convenient row access
|
||||||
|
|
||||||
- `RABBITMQ_URL`
|
### RabbitMQ Consumer (`rabbitmq_handler.py`)
|
||||||
|
|
||||||
- `MYSQL_HOST`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE`
|
- **Queue Name**: `notifications`
|
||||||
|
- **Retry Queue**: `notifications_retry`
|
||||||
|
- **Dead Letter Queue**: `notifications_dlq`
|
||||||
|
- **Max Retries**: 5 attempts
|
||||||
|
- **Retry TTL**: 30 seconds
|
||||||
|
- **Routing Key**: `notify.user.*` (standard), `notify.user.retry` (retries)
|
||||||
|
|
||||||
- `API_ENDPOINT` (Expo push API)
|
### Notification Sender (`send_notification.py`)
|
||||||
|
|
||||||
|
- **Endpoint**: `https://exp.host/--/api/v2/push/send`
|
||||||
|
- **Max Retries**: 5 attempts
|
||||||
|
- **Timeout**: 5 seconds per request
|
||||||
|
- **Backoff Strategy**: Exponential (2^attempt seconds)
|
||||||
|
|
||||||
## Metrics
|
### Message Format
|
||||||
|
|
||||||
Metrics are exposed on port `9000` for Prometheus, including:
|
Messages should be published to RabbitMQ with the following structure:
|
||||||
|
|
||||||
- `MSG_PUBLISHED`
|
```json
|
||||||
|
{
|
||||||
|
"title": "New Message",
|
||||||
|
"body": "You have a new notification",
|
||||||
|
"data": {
|
||||||
|
"category": "utility",
|
||||||
|
"link": "https://example.com",
|
||||||
|
"timestamp": "1760734800"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- `MSG_FAILED`
|
**Routing Key**: `notify.user.<user_id>` or `notify.user.retry` for retries
|
||||||
|
|
||||||
- `MSG_RETRY`
|
### Retry Messages
|
||||||
|
|
||||||
- Queue sizes
|
Retry messages include additional metadata:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "Notification Title",
|
||||||
|
"body": "Notification message body",
|
||||||
|
"uuid": "device-uuid-here",
|
||||||
|
"retry_count": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Delivery Validation
|
||||||
|
|
||||||
|
The service validates delivery results from the Expo Push API:
|
||||||
|
|
||||||
|
| Status | API Status | Action |
|
||||||
|
|--------|-----------|--------|
|
||||||
|
| `ok` | `ok` | Success - metric incremented |
|
||||||
|
| `ok` | `error` (DeviceNotRegistered) | Token expired in database |
|
||||||
|
| `ok` | `error` (other) | Sent to DLQ |
|
||||||
|
| `error` | - | Sent to DLQ |
|
||||||
|
| `failure` | - | Requeued for retry |
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
### Prometheus Metrics
|
||||||
|
|
||||||
|
Available at `http://localhost:9000/metrics`:
|
||||||
|
|
||||||
|
- `msg_published_total`: Successfully delivered notifications
|
||||||
|
- `msg_retry_total{queue_name, uuid, retry_count}`: Retry attempts
|
||||||
|
- `msg_failed_total`: Failed deliveries
|
||||||
|
- `queue_depth{queue_name}`: Current queue message counts
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Connection Issues
|
||||||
|
- `aiomysql` uses `PyMySQL` which requires the `mysql_native_password` plugin to be used. Can be checked and changed via:
|
||||||
|
```sql
|
||||||
|
SELECT user, host, plugin FROM mysql.user WHERE user='backend-push-notifications';
|
||||||
|
ALTER USER 'backend-push-notifications'@'%' IDENTIFIED WITH mysql_native_password BY 'db_password';
|
||||||
|
```
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user