Introduce a deployment recording system to track dashboard versions across environments and improve the Git management user experience. - Add `Deployment` model and Alembic migration to persist deployment history. - Implement `GitDeploymentRecorder` and `GitFingerprint` plugins to automate deployment logging and content hashing. - Add `get_deployment_status` API endpoint to retrieve real-time environment states. - Refactor `GitLifecycleHeader` to prioritize Call-to-Action (CTA) buttons and improve visual hierarchy. - Update `GitWorkspacePanel` to emphasize version saving and streamline commit workflows. - Enhance `GitEnvironmentTimeline` with deployment status integration, collapsible UI, and improved theme consistency. - Add auto-navigation logic in `GitManagerModel` to guide users to relevant tabs based on recommended actions. - Clean up obsolete documentation and update i18n strings for git visualization features.
17 KiB
Ортогональное сравнение: Наш Scheduler + Worker vs Celery и открытые альтернативы
Дата: 2026-07-10
Контекст проекта: superset-tools (FastAPI + Svelte).
Наша реализация: APScheduler (in-process) + кастомный in-process TaskManager/JobLifecycle.
Краткое резюме (TL;DR)
| Система | Архитектура | Брокер | Распределённость | Интерактивные задачи (AWAITING_*) | Реал-тайм UI/логи | Операционная сложность | Лучше всего для |
|---|---|---|---|---|---|---|---|
| Наш (APScheduler + TaskManager) | In-process (один backend) | Нет | Только вертикальная | Отличная (встроенные) | Отличная (WS + Task Center) | Низкая | Admin tools, интерактивные фоновые задачи, LLM/backup/migration внутри одного приложения |
| Celery + Beat | Producer + Broker + Workers (отдельные процессы) | Обязателен (Redis/Rabbit/...) | Отличная | Сложно (требует кастомизации) | Средняя (Flower + кастом) | Высокая | Высоконагруженные распределённые пайплайны, CPU-bound, высокая отказоустойчивость |
| APScheduler (standalone) | In-process (или с jobstores) | Нет | Ограниченная | Через кастом | Кастом | Низкая | Простые cron-задачи внутри приложения |
| Huey | Лёгкий (Redis/SQLite) | Опционально | Хорошая | Нет | Кастом | Низкая-средняя | Маленькие/средние приложения |
| RQ | Простой Redis | Redis | Хорошая | Нет | Кастом | Низкая | Простые очереди |
| Dramatiq | Современный (Redis/Rabbit) | Обязателен | Хорошая | Нет | Кастом | Средняя | Более простая/надёжная замена Celery |
| ARQ / Taskiq | Async-native (Redis-first) | Redis | Хорошая | Ограничено | Кастом | Средняя | FastAPI + высококонкурентные I/O-задачи |
| Procrastinate | Postgres-native | Нет (Postgres) | Хорошая | Ограничено | Кастом | Средняя | Когда не хочется дополнительный брокер |
Наш главный выигрыш: глубокая интеграция с UI, человеческие состояния задач (AWAITING_INPUT, AWAITING_MAPPING), real-time логи через WebSocket и нулевая дополнительная инфраструктура.
Главный проигрыш: нет горизонтального масштабирования и автоматической отказоустойчивости при падении процесса.
Что такое "наш" scheduler и worker (точные факты из кода)
Scheduler
- Файл:
backend/src/core/scheduler.py SchedulerServiceоборачиваетBackgroundScheduler(APScheduler 3.11).- Загрузка:
load_schedules()очищает все jobs и пересоздаёт из:- Backup schedules — из
config.environments[].backup_schedule. - Translation schedules — из таблицы
TranslationSchedule(is_active). - Validation policies — динамический cron +
ThrottledSchedulerConfigurator(распределение задач внутри окна).
- Backup schedules — из
- Триггеры:
CronTrigger.from_crontab(...)+ timezone. - Мост:
AsyncJobRunner(отдельный файл) —run_coroutine_threadsafe+call_laterдля delayed execution. - Нет
SQLAlchemyJobStore/ persistent jobstore — расписания восстанавливаются из прикладных таблиц и конфига при старте.
Worker / Task Execution
TaskManager(фасад) +JobLifecycle+TaskGraph+EventBus.- Создание:
create_task→asyncio.create_task(_run_task). - Выполнение:
plugin.execute(...)(async илиasyncio.to_thread). - Ограничение блокирующих операций: именованные
ThreadPoolExecutor(db/file/git) —core/utils/executors.py(ADR-0011). - Состояния:
PENDING → RUNNING → SUCCESS/FAILED+AWAITING_MAPPING/AWAITING_INPUT. - Персистентность: отдельная таблица
task_records+task_logs(может бытьTASKS_DATABASE_URL= основной или sqlite). - Реал-тайм:
EventBus(asyncio.Queue) → WS для логов, статуса, событий датасетов. - Интерактивность:
resume_task_with_password,resolve_task— задачи реально "парятся" и ждут пользователя. - Деплой: один контейнер
backend(docker-compose.yml). Нет отдельного worker-сервиса.
ADR-0011 явно отвергает multiprocessing workers и брокер в пользу async + bounded executors внутри процесса.
Ортогональные проекции (13 измерений)
1. Architecture & Deployment Model
Наш: Монолитный процесс (API + scheduler + executor).
Celery: Три отдельных роли (app, beat, worker(s)) + брокер.
ARQ/Taskiq: Async workers как отдельные процессы/контейнеры.
Huey/RQ: Лёгкие отдельные worker-процессы.
APScheduler standalone: Обычно в том же процессе, что и приложение.
Вывод: Наш — самый простой в деплое (один сервис).
2. External Dependencies & Operational Surface
Наш: Только основная БД (опционально отдельная для задач). APScheduler — чисто in-memory.
Celery: Брокер + результат + мониторинг (Flower) + beat.
Dramatiq/ARQ: Брокер обязателен.
Procrastinate: Только Postgres.
Наш выигрывает по операционной простоте.
3. Scheduling (Cron + Dynamic jobs)
Наш: Полноценный Cron + динамическое добавление/удаление/перезагрузка из нескольких источников. Throttling внутри окон.
Celery Beat: Cron/interval + django-celery-beat для динамики.
APScheduler: Лучший в классе триггеров (date/interval/cron) + jobstores.
Huey: Periodic tasks через huey.contrib.
RQ: Нет встроенного — внешний планировщик или rq-scheduler.
Наш: Очень удобен для пользовательских расписаний (translate, validation, backup).
4. Task Execution Model & Concurrency
Наш: asyncio + bounded thread pools внутри event loop. Плагины выполняются в контексте приложения.
Celery: Отдельные процессы (prefork/eventlet/gevent).
ARQ/Taskiq: Нативный asyncio в worker'ах.
Dramatiq: Sync-first (можно с gevent).
Для I/O-heavy (LLM, HTTP к Superset, Git) async-модели (наш + ARQ) эффективнее по вертикали.
5. Scalability & Distribution
Наш: Только вертикальная (добавить CPU/RAM одной ноде). При нескольких backend'ах — дублирование расписаний.
Celery / большинство очередей: Линейное горизонтальное масштабирование (добавляй workers).
APScheduler с RedisJobStore: Ограниченная распределённость.
Наш не предназначен для десятков тысяч задач в минуту.
6. Reliability, Resilience & Fault Tolerance
Наш:
- Расписания восстанавливаются при рестарте.
- Задачи сохраняют состояние.
- Проблема: RUNNING задачи при падении процесса не возобновляются автоматически. AWAITING_* требуют ручного рестарта.
- Нет встроенных ретраев на уровне очереди.
Celery: Ack, redeliver, retries, max_retries, dead-letter, result backend.
Dramatiq: Хорошие ретраи по умолчанию.
Procrastinate: Надёжность Postgres.
Критично для нас: если задача "перевода 200k строк" упала вместе с backend — нужно перезапускать вручную.
7. Task Lifecycle Richness & Advanced Features
Наш — лидер в своей нише:
- AWAITING_INPUT (пароли БД)
- AWAITING_MAPPING (разрешение ресурсов)
- TaskContext для structured logging
- Отмена, resume, resolve через API
Celery: canvas (chain/group/chord), routing, priority, eta/countdown, rate_limit, task_revocation.
Остальные: базовые retry + простые очереди. Интерактивность почти ни у кого нет "из коробки".
Это одно из самых сильных конкурентных преимуществ нашего решения для инструмента администратора.
8. Observability, Monitoring & UX Integration
Наш:
- Нативный Task Status Center (spec 034)
- WebSocket real-time логи + статус
- Фильтры, summary, drawer с логами
- RBAC на уровне задач
Celery: Flower (отдельное приложение), Prometheus экспортеры, кастом.
Другие: обычно только логи + кастомный дашборд.
Наш выигрывает для пользователей продукта (не только DevOps).
9. Persistence (Schedules + Task State/Results/Logs)
Наш:
- Расписания — в прикладных таблицах + config.
- Задачи/логи —
task_records/task_logs(JSON + отдельная таблица логов). - Высокопроизводительная батчевая запись логов.
Celery: Результаты в отдельном backend (Redis/Postgres/…). Задачи обычно не хранят детальные логи внутри. APScheduler + SQLAlchemyJobStore: Полная персистентность расписаний. Huey: Опционально SQLite/Redis.
10. Resource Footprint, Isolation & Performance Profile
Наш: Низкий overhead. Всё в одном процессе. Bounded pools дают backpressure.
Celery prefork: Выше потребление памяти, хорошая изоляция.
Async workers (ARQ): Отличная плотность I/O-задач на ядро.
CPU-bound задачи: Процессные модели лучше (изоляция GIL).
Для наших задач (LLM, Superset API, Git, batch SQL) in-process async + pools работает отлично.
11. Ease of Development, Testing & Integration (FastAPI)
Наш: Плагины просто реализуют execute. Всё в одном codebase. Легко тестировать с TaskContext.
Celery: Отдельный app, сериализация, импорт проблем, тесты сложнее.
ARQ/Taskiq: Хорошая интеграция с FastAPI (async-native).
APScheduler: Самый простой для простых cron.
12. Ecosystem, Maturity & Maintenance Burden
- Celery: Самая зрелая, огромная экосистема, но репутация "сложная и полна сюрпризов".
- APScheduler: Зрелая, активно поддерживается.
- Dramatiq: Создавалась как "лучше Celery".
- ARQ: От автора Pydantic/FastAPI — отличный современный выбор.
- Huey/RQ: Простые, меньше "магии".
Наш — полностью кастомный слой поверх APScheduler. Поддержка ложится на команду проекта.
13. Best-fit Use Cases & Trade-off Summary
Идеально для нас сегодня:
- Инструмент администратора Superset.
- Задачи с человеческим участием.
- Реал-тайм обратная связь важнее горизонтального масштаба.
- Минимальная операционная нагрузка.
Когда стоит рассмотреть Celery/ARQ/Dramatiq:
- Появятся десятки тысяч фоновых задач.
- Нужна настоящая отказоустойчивость (задача должна дожить до выполнения даже при рестарте всего кластера).
- CPU-heavy работа (большие вычисления, не I/O).
- Несколько независимых сервисов, которые должны шарить очередь.
Гибрид возможен: оставить текущий механизм для UI-driven и scheduled admin-задач, а тяжёлые batch-операции вынести в отдельную очередь.
Сравнительная матрица (сводка)
(См. TL;DR таблицу выше + детальные проекции.)
Рекомендация для superset-tools
Оставить текущую архитектуру как основную.
Причины:
- Отлично соответствует текущим потребностям (переводы, бэкапы, валидации, миграции, git).
- Уникальные фичи (AWAITING_*, TaskContext, нативный красивый Task Center) очень ценны для пользователей.
- Низкая операционная сложность — большое преимущество.
- ADR-0011 и вся эволюция проекта сознательно шли в эту сторону.
Что можно улучшить без революции (опционально):
- Добавить
SQLAlchemyJobStoreили RedisJobStore для расписаний (защита от потери при странных рестартах). - Добавить автоматический "reconcile" для зависших RUNNING задач при старте (по таймауту или heartbeat).
- Для очень тяжёлых переводов — рассмотреть возможность выноса в отдельный worker позже.
Не переходить на Celery "на всякий случай" — это добавит значительную сложность без немедленной пользы.
Источники
- Код проекта:
backend/src/core/scheduler.py,task_manager/*,ADR-0011-async-backend.md, docker-compose. - Внешние сравнения:
- APScheduler vs Celery Beat (leapcell.io, 2025) [web:3].
- Reddit 2026: "Choosing a Python task queue library".
- Dramatiq motivation page.
- ARQ adoption stories и бенчмарки (см. также [web:0], [web:9]).
- StackShare / официальная документация.
Сравнение выполнено ортогонально — по независимым измерениям, без навязывания одного "лучшего" решения.