init push
This commit is contained in:
157
docs/queue-sqs-migration.md
Normal file
157
docs/queue-sqs-migration.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# Queue Migration Notes
|
||||
|
||||
This project no longer supports Redis as a runtime dependency. Queue publishing and consumption are SQS-only, while transient auth/runtime state is stored in MySQL.
|
||||
|
||||
## Current Flow
|
||||
|
||||
1. API writes business data to MySQL.
|
||||
2. If `QUEUE_OUTBOX_ENABLED=true`, email jobs are persisted to `email_outbox_messages`.
|
||||
3. Worker polls the outbox and publishes serialized messages to SQS.
|
||||
4. Worker consumes SQS messages with long polling and sends email through Amazon SES v2.
|
||||
5. Successful processing deletes the SQS message.
|
||||
6. Failed processing leaves the message unacked so SQS visibility timeout and DLQ redrive policy handle retries.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Removed Redis producer, consumer, and Redis-backed idempotency paths.
|
||||
- Removed Redis token store used for:
|
||||
- refresh/session bookkeeping
|
||||
- SSO state
|
||||
- TOTP/WebAuthn challenges
|
||||
- security PIN lock/cooldown state
|
||||
- Added MySQL-backed transient stores:
|
||||
- `auth_runtime_tokens`
|
||||
- `queue_idempotency_records`
|
||||
- Simplified bootstrap:
|
||||
- API uses MySQL + optional direct SQS publisher when outbox is disabled.
|
||||
- Worker uses MySQL + SQS only.
|
||||
|
||||
## Required Environment
|
||||
|
||||
Queue and worker settings:
|
||||
|
||||
```bash
|
||||
EMAIL_PROVIDER=mock
|
||||
EMAIL_MOCK_DIR=.local/emails
|
||||
|
||||
QUEUE_MESSAGE_SCHEMA_VERSION=v2
|
||||
QUEUE_ENABLE_LEGACY_PAYLOAD_FALLBACK=true
|
||||
QUEUE_IDEMPOTENCY_KEY_PREFIX=queue:idempotency:email:
|
||||
QUEUE_IDEMPOTENCY_TTL=24h
|
||||
QUEUE_PROCESSING_TTL=15m
|
||||
QUEUE_WORKER_CONCURRENCY=4
|
||||
QUEUE_WORKER_MAX_BATCH_SIZE=10
|
||||
QUEUE_WORKER_PROCESS_TIMEOUT=30s
|
||||
QUEUE_WORKER_SHUTDOWN_TIMEOUT=30s
|
||||
QUEUE_WORKER_BACKOFF_MIN=1s
|
||||
QUEUE_WORKER_BACKOFF_MAX=5m
|
||||
QUEUE_WORKER_PERMANENT_FAILURE_DELAY=30s
|
||||
QUEUE_WORKER_MONITOR_ADDR=127.0.0.1:9090
|
||||
QUEUE_WORKER_HEALTH_ERROR_THRESHOLD=3
|
||||
QUEUE_WORKER_DEPTH_POLL_INTERVAL=30s
|
||||
QUEUE_OUTBOX_ENABLED=true
|
||||
QUEUE_OUTBOX_POLL_INTERVAL=1s
|
||||
QUEUE_OUTBOX_BATCH_SIZE=10
|
||||
QUEUE_OUTBOX_DISPATCH_TIMEOUT=10s
|
||||
QUEUE_OUTBOX_LOCK_TTL=1m
|
||||
QUEUE_OUTBOX_MAX_ATTEMPTS=20
|
||||
```
|
||||
|
||||
SES settings:
|
||||
|
||||
```bash
|
||||
AWS_REGION=ap-southeast-1
|
||||
SES_REGION=
|
||||
SES_FROM=no-reply@example.com
|
||||
SES_CONFIGURATION_SET=
|
||||
SES_SEND_TIMEOUT=10s
|
||||
SES_ENDPOINT=
|
||||
SES_ALLOW_INSECURE_ENDPOINT=false
|
||||
```
|
||||
|
||||
Local/dev recommendation when you do not have AWS SES:
|
||||
|
||||
- set `EMAIL_PROVIDER=mock`
|
||||
- keep SQS on LocalStack if needed
|
||||
- inspect delivered mock emails in `EMAIL_MOCK_DIR`
|
||||
|
||||
AWS / SQS settings:
|
||||
|
||||
```bash
|
||||
AWS_REGION=ap-southeast-1
|
||||
SQS_ENDPOINT=
|
||||
SQS_ALLOW_INSECURE_ENDPOINT=false
|
||||
SQS_QUEUE_URL=https://sqs.ap-southeast-1.amazonaws.com/123456789012/wucher-email
|
||||
SQS_QUEUE_TYPE=standard
|
||||
SQS_MESSAGE_GROUP_ID=email
|
||||
SQS_MAX_MESSAGES=10
|
||||
SQS_WAIT_TIME_SECONDS=20
|
||||
SQS_VISIBILITY_TIMEOUT=60s
|
||||
```
|
||||
|
||||
## SQS Expectations
|
||||
|
||||
Configure the queue outside the application with:
|
||||
|
||||
- long polling enabled
|
||||
- sensible visibility timeout
|
||||
- DLQ redrive policy
|
||||
- `maxReceiveCount` aligned with retry tolerance
|
||||
|
||||
Recommended baseline:
|
||||
|
||||
- `ReceiveMessageWaitTimeSeconds=20`
|
||||
- `VisibilityTimeout=60`
|
||||
- `maxReceiveCount=5`
|
||||
|
||||
## IAM
|
||||
|
||||
API needs `sqs:SendMessage` only when `QUEUE_OUTBOX_ENABLED=false`.
|
||||
|
||||
Worker needs:
|
||||
|
||||
- `sqs:SendMessage` to the main queue when dispatching outbox messages
|
||||
- `sqs:ReceiveMessage`
|
||||
- `sqs:DeleteMessageBatch`
|
||||
- `sqs:ChangeMessageVisibility`
|
||||
- `sqs:GetQueueAttributes`
|
||||
- `ses:SendEmail`
|
||||
|
||||
If SES event tracking is enabled, provision it separately with:
|
||||
|
||||
- SES configuration set event destinations
|
||||
- SNS topic publish permissions
|
||||
- a dedicated SQS event queue and consumer policy
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- Remove these Redis env vars from deployment:
|
||||
- `REDIS_ADDR`
|
||||
- `REDIS_PASSWORD`
|
||||
- `REDIS_DB`
|
||||
- `QUEUE_PRIMARY_BACKEND`
|
||||
- `QUEUE_SECONDARY_BACKEND`
|
||||
- `QUEUE_SECONDARY_REQUIRED`
|
||||
- `QUEUE_CONSUMER_BACKEND`
|
||||
- `QUEUE_IDEMPOTENCY_BACKEND`
|
||||
- `QUEUE_PRODUCER_MODE`
|
||||
- `QUEUE_REDIS_DLQ_KEY`
|
||||
- `AUTH_EMAIL_QUEUE_KEY`
|
||||
- `SQS_DLQ_URL`
|
||||
- Worker now requires MySQL even when it is only consuming SQS, because idempotency state is persisted in MySQL.
|
||||
- Old Redis backlog is not consumed by this version. Drain or discard legacy Redis queues before deploy.
|
||||
|
||||
## Deployment Checklist
|
||||
|
||||
1. Ensure MySQL migration/AutoMigrate runs and creates `auth_runtime_tokens` and `queue_idempotency_records`.
|
||||
2. Create or verify the SQS queue and DLQ redrive policy.
|
||||
3. Verify the SES identity/domain and optional configuration set.
|
||||
4. Remove Redis and SMTP config from runtime manifests and secrets.
|
||||
5. Deploy API and worker.
|
||||
6. Verify:
|
||||
- worker `/health`
|
||||
- worker `/metrics`
|
||||
- SQS queue depth
|
||||
- outbox rows are progressing from `pending` to `published`
|
||||
- SES send acceptance/message IDs in worker logs
|
||||
7. Manually delete Redis infrastructure after confirming there is no remaining backlog you still need.
|
||||
Reference in New Issue
Block a user