Logo

~/saidqb cat wiki/stack/server-extra/fastapi.md

MDfastapi.md

commit by saidqb

FastAPI: setup tambahan (Queue, WebSocket, Scheduler)

Lanjutan dari deploy-fastapi.md — versi FastAPI dari 3 topik yang sama dibahas di laravel.md, walau caranya beda karena FastAPI tidak punya queue/scheduler bawaan seperti Laravel. Path & user (fastapiapp, /home/fastapiapp/app) ikut konvensi dokumen deploy utama.

1. Background job queue (Celery + Redis)

FastAPI tidak punya queue bawaan — yang paling umum dipakai Celery dengan Redis sebagai broker (antrian job-nya nyimpen di Redis, worker Celery yang proses).

sudo apt install redis-server -y
sudo -iu fastapiapp
cd app
source venv/bin/activate
pip install celery redis
exit

Buat celery_app.py di root project (contoh minimal):

from celery import Celery

celery_app = Celery("app", broker="redis://localhost:6379/0", backend="redis://localhost:6379/0")

/etc/systemd/system/fastapiapp-celery.service

[Unit]
Description=Celery worker for FastAPI app
After=network.target redis-server.service

[Service]
User=fastapiapp
Group=fastapiapp
WorkingDirectory=/home/fastapiapp/app
ExecStart=/home/fastapiapp/app/venv/bin/celery -A celery_app worker --loglevel=info
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now fastapiapp-celery

Redis default cuma listen di localhost, jadi tidak perlu dibuka di firewall/Nginx — cuma diakses internal oleh app & worker di server yang sama.

Kalau kebutuhannya ringan (job sederhana, tidak butuh fitur Celery yang banyak), RQ (Redis Queue) alternatif yang lebih simpel — API-nya jauh lebih kecil, worth dicoba dulu sebelum lompat ke Celery.

2. WebSocket

Beda penting dari Reverb-nya Laravel: FastAPI sudah built-in dukungan WebSocket (lewat Starlette) — proses Uvicorn/Gunicorn yang sama di deploy-fastapi.md sudah otomatis bisa nanganin route @app.websocket(...), tidak perlu service terpisah.

Yang perlu diubah cuma block Nginx yang sudah ada (deploy-fastapi.md Langkah 4) — tambahkan header upgrade koneksi:

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
sudo nginx -t && sudo systemctl reload nginx

Catatan kalau -w 4 (4 worker Gunicorn) di systemd service: tiap koneksi WebSocket "nempel" ke salah satu worker yang nerima koneksinya — kalau perlu broadcast pesan ke semua client dari worker manapun (chat app, notifikasi realtime), butuh sesuatu buat fan-out antar-worker (Redis pub/sub paling umum), bukan cuma andalkan memori satu proses.

3. Scheduled tasks

FastAPI juga tidak punya scheduler bawaan (beda dari Laravel yang punya $schedule->...). Tiga pilihan, dari yang paling simpel:

Opsi A — cron biasa, cocok buat script yang jalan sendiri lepas dari proses app:

sudo -u fastapiapp crontab -e
0 * * * * cd /home/fastapiapp/app && venv/bin/python scripts/hourly_task.py >> /dev/null 2>&1

Opsi B — APScheduler, jalan in-process di dalam app itu sendiri (cocok kalau jadwalnya perlu akses langsung ke state/koneksi app):

pip install apscheduler
from apscheduler.schedulers.background import BackgroundScheduler

scheduler = BackgroundScheduler()
scheduler.add_job(my_task, "interval", minutes=30)

@app.on_event("startup")
def start_scheduler():
    scheduler.start()

Opsi C — Celery Beat, kalau sudah pakai Celery dari Langkah 1 — satu service systemd tambahan (celery -A celery_app beat), jadwalnya didefinisikan di kode Python, mirip konsep Task Scheduler Laravel.