- Extract ADR documents for architectural decisions (SQLite, FastAPI, React, APScheduler, Scheduler) - Refactor setup.py: improve code structure and readability - Add IP validation utilities with test coverage - Update frontend components (BanTable, HistoryPage) - Add pre-commit hooks and CONTRIBUTING.md - Add .editorconfig for consistent coding standards
2.2 KiB
2.2 KiB
ADR-004: APScheduler over Celery
Status
Accepted
Context
BanGUI requires background task scheduling for periodic work: geo cache flush, session cleanup, history sync, and blocklist imports.
Decision
Use APScheduler 4.x (AsyncIOScheduler) for background scheduling.
Rationale
Why APScheduler over Celery?
- No infrastructure: Celery requires a message broker (Redis or RabbitMQ). APScheduler runs in-process with no broker. Given BanGUI's single-instance constraint, a message queue adds unnecessary operational complexity.
- Async-native:
AsyncIOSchedulerintegrates directly with the asyncio event loop. All BanGUI's I/O (database, HTTP, fail2ban socket) is async. APScheduler jobs areasync deffunctions thatawaitwithout blocking. - Simplicity: BanGUI's job set is fixed and small. Celery's rich task routing, retry policies, and distributed execution are overkill. APScheduler covers cron-style scheduling with simpler semantics.
- Single-instance enforcement: APScheduler's in-memory job store is a natural fit when there is only one scheduler. No distributed coordination needed.
Why not Celery?
- Celery's architecture (broker + workers + result backend) is designed for distributed systems. BanGUI is explicitly single-instance.
- Celery tasks are synchronous wrappers around async code without careful
handling. Native
async deftasks requireasync_task()or explicitrun_sync, creating friction in an async-first codebase. - Added operational burden: Redis or RabbitMQ must be available at startup.
Trade-offs
- No horizontal scaling of workers: APScheduler jobs run in the single uvicorn worker process. CPU-intensive jobs would block the event loop. (This is not a concern for BanGUI's I/O-bound jobs.)
- No built-in retry mechanism: Failed jobs must re-raise exceptions or implement retry logic manually. This is acceptable given BanGUI's job idempotency guarantees.
Consequences
- Scheduler is configured in
app/startup.pyusingAsyncIOScheduler. - Jobs live in
app/tasks/. - Single-worker constraint is enforced via
BANGUI_WORKERS=1validation and thescheduler_lockdatabase table.