155 lines
13 KiB
Plaintext
155 lines
13 KiB
Plaintext
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
║ MULTI-WORKER FASTAPI ARCHITECTURE ║
|
|
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ Command: uvicorn alpine_bits_python.api:app --workers 4 │
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
┃ Master Process (uvicorn supervisor) ┃
|
|
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
│ │ │ │
|
|
┌───────────┼──────────┼──────────┼──────────┼───────────┐
|
|
│ │ │ │ │ │
|
|
▼ ▼ ▼ ▼ ▼ ▼
|
|
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌──────────────────┐
|
|
│Worker 0│ │Worker 1│ │Worker 2│ │Worker 3│ │Lock File │
|
|
│PID:1001│ │PID:1002│ │PID:1003│ │PID:1004│ │/tmp/alpinebits │
|
|
└────┬───┘ └───┬────┘ └───┬────┘ └───┬────┘ │_primary_worker │
|
|
│ │ │ │ │.lock │
|
|
│ │ │ │ └──────────────────┘
|
|
│ │ │ │ ▲
|
|
│ │ │ │ │
|
|
└─────────┴──────────┴──────────┴─────────────┤
|
|
All try to acquire lock │
|
|
│ │
|
|
▼ │
|
|
┌───────────────────────┐ │
|
|
│ fcntl.flock(LOCK_EX) │────────────┘
|
|
│ Non-blocking attempt │
|
|
└───────────────────────┘
|
|
│
|
|
┏━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┓
|
|
▼ ▼
|
|
┌─────────┐ ┌──────────────┐
|
|
│SUCCESS │ │ WOULD BLOCK │
|
|
│(First) │ │(Others) │
|
|
└────┬────┘ └──────┬───────┘
|
|
│ │
|
|
▼ ▼
|
|
|
|
╔════════════════════════════════╗ ╔══════════════════════════════╗
|
|
║ PRIMARY WORKER ║ ║ SECONDARY WORKERS ║
|
|
║ (Worker 0, PID 1001) ║ ║ (Workers 1-3) ║
|
|
╠════════════════════════════════╣ ╠══════════════════════════════╣
|
|
║ ║ ║ ║
|
|
║ ✓ Handle HTTP requests ║ ║ ✓ Handle HTTP requests ║
|
|
║ ✓ Start email scheduler ║ ║ ✗ Skip email scheduler ║
|
|
║ ✓ Send daily reports ║ ║ ✗ Skip daily reports ║
|
|
║ ✓ Run DB migrations ║ ║ ✗ Skip DB migrations ║
|
|
║ ✓ Hash customers (startup) ║ ║ ✗ Skip customer hashing ║
|
|
║ ✓ Send error alerts ║ ║ ✓ Send error alerts ║
|
|
║ ✓ Process webhooks ║ ║ ✓ Process webhooks ║
|
|
║ ✓ AlpineBits endpoints ║ ║ ✓ AlpineBits endpoints ║
|
|
║ ║ ║ ║
|
|
║ Holds: worker_lock ║ ║ worker_lock = None ║
|
|
║ ║ ║ ║
|
|
╚════════════════════════════════╝ ╚══════════════════════════════╝
|
|
│ │
|
|
│ │
|
|
└──────────┬───────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────────┐
|
|
│ Incoming HTTP Request │
|
|
└───────────────────────────┘
|
|
│
|
|
(Load balanced by OS)
|
|
│
|
|
┌───────────┴──────────────┐
|
|
│ │
|
|
▼ ▼
|
|
Any worker can handle Round-robin distribution
|
|
the request normally across all 4 workers
|
|
|
|
|
|
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
║ SINGLETON SERVICES ║
|
|
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
|
|
Only run on PRIMARY worker:
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Email Scheduler │
|
|
│ ├─ Daily Report: 8:00 AM │
|
|
│ └─ Stats Collection: Per-hotel reservation counts │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Startup Tasks (One-time) │
|
|
│ ├─ Database table creation │
|
|
│ ├─ Customer data hashing/backfill │
|
|
│ └─ Configuration validation │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
║ SHARED SERVICES ║
|
|
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
|
|
Run on ALL workers (primary + secondary):
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ HTTP Request Handling │
|
|
│ ├─ Webhook endpoints (/api/webhook/*) │
|
|
│ ├─ AlpineBits endpoints (/api/alpinebits/*) │
|
|
│ └─ Health checks (/api/health) │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Error Alert Handler │
|
|
│ └─ Any worker can send immediate error alerts │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Event Dispatching │
|
|
│ └─ Background tasks triggered by webhooks │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
║ SHUTDOWN & FAILOVER ║
|
|
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
|
|
Graceful Shutdown:
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 1. SIGTERM received │
|
|
│ 2. Stop scheduler (primary only) │
|
|
│ 3. Close email handler │
|
|
│ 4. Release worker_lock (primary only) │
|
|
│ 5. Dispose database engine │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
Primary Worker Crash:
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 1. Primary worker crashes │
|
|
│ 2. OS automatically releases file lock │
|
|
│ 3. Secondary workers continue handling requests │
|
|
│ 4. On next restart, first worker becomes new primary │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
║ KEY BENEFITS ║
|
|
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
|
|
✓ No duplicate email notifications
|
|
✓ No race conditions in database operations
|
|
✓ Automatic failover if primary crashes
|
|
✓ Load distribution for HTTP requests
|
|
✓ No external dependencies (Redis, etc.)
|
|
✓ Simple and reliable
|
|
|