refactor(workers): split celery_app.py god-object into 3 modules #135

Merged
lekss361 merged 1 commit from refactor/split-celery-app-134 into main 2026-05-14 21:09:38 +00:00
lekss361 commented 2026-05-14 21:05:13 +00:00 (Migrated from github.com)

Summary

Per audit batch #127 P3 god objects: split `celery_app.py` (270 lines) на 3 self-contained модуля.

Split layout

File Before After Role
`celery_app.py` 270 35 App config (broker/backend/timezone/includes), bootstraps beat + lifecycle
`beat_schedule.py` 207 (NEW) DB-driven + fallback + hardcoded beat schedule
`lifecycle.py` 168 (NEW) Worker signal handlers (process_init, worker_ready)

No behavior changes

Move-only structural refactor. `celery_app.conf.beat_schedule` populated same way; signal handlers register via side-effect import. Public API unchanged.

Verify

```
beat_schedule keys: ['kn-region-66', 'objective_sync',
'refresh-ekb-districts-medians', 'nspd-geo-zombie-cleanup',
'poi-sync-weekly', 'noise-sync-weekly']
```

  • ruff + ruff-format: clean
  • AST parse: OK
  • Tests: 0 existed для этого слоя (ortogonal issue, not blocker)

Vault

  • `code/modules/Module_Beat_Schedule.md` (NEW)
  • `code/modules/Module_Worker_Lifecycle.md` (NEW)
  • `domains/infra/Module_Celery_App.md` (updated)

Closes #134
Refs: #127

## Summary Per audit batch #127 P3 god objects: split \`celery_app.py\` (270 lines) на 3 self-contained модуля. ## Split layout | File | Before | After | Role | |---|---:|---:|---| | \`celery_app.py\` | 270 | **35** | App config (broker/backend/timezone/includes), bootstraps beat + lifecycle | | \`beat_schedule.py\` | — | 207 (NEW) | DB-driven + fallback + hardcoded beat schedule | | \`lifecycle.py\` | — | 168 (NEW) | Worker signal handlers (process_init, worker_ready) | ## No behavior changes Move-only structural refactor. \`celery_app.conf.beat_schedule\` populated same way; signal handlers register via side-effect import. Public API unchanged. ## Verify \`\`\` beat_schedule keys: ['kn-region-66', 'objective_sync', 'refresh-ekb-districts-medians', 'nspd-geo-zombie-cleanup', 'poi-sync-weekly', 'noise-sync-weekly'] \`\`\` - ruff + ruff-format: clean - AST parse: OK - Tests: 0 existed для этого слоя (ortogonal issue, not blocker) ## Vault - \`code/modules/Module_Beat_Schedule.md\` (NEW) - \`code/modules/Module_Worker_Lifecycle.md\` (NEW) - \`domains/infra/Module_Celery_App.md\` (updated) Closes #134 Refs: #127
lekss361 commented 2026-05-14 21:09:31 +00:00 (Migrated from github.com)

Bot review (SHA dd3c126, CI )

Чистый structural split, behavior-preserving.

Проверка wiring (главная зона риска при таком split'е)

В celery_app.py после Celery() инстанциации:

from app.workers.beat_schedule import build_beat_schedule  # noqa: E402
celery_app.conf.beat_schedule = build_beat_schedule()

from app.workers import lifecycle  # noqa: E402, F401

beat_schedule explicitly applied — функция вызывается, результат присваивается. Не «остаётся надеяться что side-effect сработает».
lifecycle side-effect import@worker_process_init.connect / @worker_ready.connect декораторы выполняются на load lifecycle module. # noqa: F401 корректно подавляет unused-import warning для intentional side-effect pattern. Это идиома Celery ecosystem.
Порядок имеет значение и соблюдёнcelery_app = Celery(...) создан ДО импорта lifecycle (handlers ссылаются на signals, не на celery_app instance, так что технически порядок не критичен, но логически чистый).
CI green включая backend job — циркулярные импорты были бы пойманы при импорте celery_app в conftest.

Скоупы

File Lines Содержит
celery_app.py ~37 Celery() + conf + 2 import'а
beat_schedule.py +241 TASK_MAP, _parse_cron, _default_regions, _build_beat_schedule_from_db, _build_beat_schedule_fallback, build_beat_schedule + 4 hardcoded jobs (zombie, poi, noise)
lifecycle.py +216 _reset_db_connections (worker_process_init), _resume_zombie_runs (worker_ready) + helpers

Закомментированный nspd-harvest-stale-quarters block из PR #121 правильно перенесён в beat_schedule.py (post-mortem trail preserved).

Минор (не блокер)

Стилистически, явная функция register_lifecycle_hooks() была бы read-friendlier чем side-effect import + noqa, но это вкусовщина — текущий подход идиоматичен для Celery.

approve merge

## Bot review (SHA `dd3c126`, CI ✅) Чистый structural split, behavior-preserving. ### Проверка wiring (главная зона риска при таком split'е) В `celery_app.py` после Celery() инстанциации: ```python from app.workers.beat_schedule import build_beat_schedule # noqa: E402 celery_app.conf.beat_schedule = build_beat_schedule() from app.workers import lifecycle # noqa: E402, F401 ``` ✅ **beat_schedule explicitly applied** — функция вызывается, результат присваивается. Не «остаётся надеяться что side-effect сработает». ✅ **lifecycle side-effect import** — `@worker_process_init.connect` / `@worker_ready.connect` декораторы выполняются на load lifecycle module. `# noqa: F401` корректно подавляет unused-import warning для intentional side-effect pattern. Это идиома Celery ecosystem. ✅ **Порядок имеет значение и соблюдён** — `celery_app = Celery(...)` создан ДО импорта lifecycle (handlers ссылаются на signals, не на celery_app instance, так что технически порядок не критичен, но логически чистый). ✅ **CI green** включая backend job — циркулярные импорты были бы пойманы при импорте celery_app в conftest. ### Скоупы | File | Lines | Содержит | |---|---:|---| | `celery_app.py` | ~37 | Celery() + conf + 2 import'а | | `beat_schedule.py` | +241 | TASK_MAP, _parse_cron, _default_regions, _build_beat_schedule_from_db, _build_beat_schedule_fallback, build_beat_schedule + 4 hardcoded jobs (zombie, poi, noise) | | `lifecycle.py` | +216 | _reset_db_connections (worker_process_init), _resume_zombie_runs (worker_ready) + helpers | Закомментированный `nspd-harvest-stale-quarters` block из PR #121 правильно перенесён в `beat_schedule.py` (post-mortem trail preserved). ### Минор (не блокер) Стилистически, явная функция `register_lifecycle_hooks()` была бы read-friendlier чем side-effect import + `noqa`, но это вкусовщина — текущий подход идиоматичен для Celery. approve merge
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#135
No description provided.