Skip to content

SEP-1551: Derive Celery include and beat seed prefixes from the app registry - #1121

Merged
marcuscruz-percona merged 8 commits into
mainfrom
SEP-1551
Jul 15, 2026
Merged

SEP-1551: Derive Celery include and beat seed prefixes from the app registry#1121
marcuscruz-percona merged 8 commits into
mainfrom
SEP-1551

Conversation

@marcuscruz-percona

Copy link
Copy Markdown
Contributor

Summary

  • Apps declare their Celery task module via App.celery_module_path, a three-state field mirroring api_router_path (auto-derive <module>.celery from a filesystem probe, explicit string override, or explicit null opt-out); the worker include list and beat task_name prefixes both derive from that single source, so a module rename can no longer desync the include from the seed.
  • AppRegistry exposes the ordered app-owned Celery module paths; build_celery_include composes static base + registry-derived app modules and is the one seam both the Celery-app assembly and the worker bootstrap call.
  • A system periodic-task schedule is emitted only when its owning app contributes a Celery module — an absent or opted-out app yields no schedule instead of a None-prefixed task_name; an explicit override is filesystem-probed at settings construction so a typo fails at load, not at worker import.

Deviation from AC (flagged): CeleryOptions.set_include seeds only the static base rather than composing the app modules itself. Reaching the app registry during core Settings construction forces sep_settings, which reads core settings back through the same un-guarded lazy proxy and re-enters a half-built Settings. Composition therefore happens at a safe seam (build_celery_include) after core settings is fully built; nothing consumes Celery config before app.celery is imported, which is where composition runs.

Tested

  • Targeted regression: config, registry, celery_registration, seed, settings-override integration, main — 160 passed.
  • Runtime smoke: settings.CELERY.include == build_celery_include() == celery.conf.include == ['app.tasks.celery', 'app.sep.apps.snippets.celery', 'app.sep.apps.alerts.celery', 'app.sep.apps.report.celery'].
  • make checkmigrations clean (no migration; beat rows re-seed by stable name).

Checklist

  • New/modified functions have type hints and rST docstrings
  • New tests added for new features or bug fixes
  • All tests pass locally (make test) — ran targeted regression (160 passed), not the full suite
  • Pre-commit hooks pass (make run-pre-commit)
  • Database migrations generated if models changed (make makemigrations) — N/A, no model change
  • User-facing changes documented (README, inline help, UI text) — N/A
  • Configuration changes documented with examples — App.celery_module_path documented in the field docstring
  • Changelog fragment added under changelog.d/

Apps declare their Celery module via App.celery_module_path, a three-state
field mirroring api_router_path (auto-derive <module>.celery from a filesystem
probe, explicit string override, or explicit null opt-out). The worker include
list and beat task_name prefixes both derive from that single source, so a
module rename can no longer desync the include from the seed.

- set_include seeds only the static service base (app.tasks.celery); the
  registry-derived app modules are composed at a safe seam
  (build_celery_include, called from Celery-app assembly and worker start)
  because reaching the registry during core Settings construction re-enters the
  half-built lazy proxy.
- An explicit celery_module_path override is filesystem-probed at settings
  construction so a typo fails at load rather than at worker import.
- A system periodic-task schedule is emitted only when its owning app
  contributes a Celery module, so an absent or opted-out app yields no schedule
  instead of a None-prefixed task_name pointing at nothing the worker registers.

No database migration: beat rows re-seed by their stable name.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR centralizes SEP’s Celery module discovery by introducing App.celery_module_path and deriving both the worker include list and SEP beat seed task_name prefixes from the same app-registry-derived source, preventing drift when app task modules move/rename.

Changes:

  • Add App.celery_module_path (three-state: omitted/explicit string/explicit null) with filesystem-based validation during settings construction.
  • Introduce registry helpers (app_celery_module_paths, app_celery_module_for, build_celery_include) and plumb them into Celery app assembly, worker bootstrap, and SEP beat seeding (including “no celery module → no schedule” gating).
  • Add/extend tests covering derivation, gating behavior, and invariants; add a changelog fragment.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
app/core/celery/config.py Introduces STATIC_CELERY_INCLUDE and narrows CeleryOptions.set_include to seed the static base only.
app/celery.py Composes the final settings.CELERY.include via build_celery_include() at Celery app assembly time.
app/main.py Updates worker bootstrap to use build_celery_include() instead of a hardcoded include list.
app/sep/config.py Adds App.celery_module_path plus convention-based defaulting and filesystem existence validation.
app/sep/apps/framework/registry.py Exposes ordered app celery module paths and provides build_celery_include() for shared composition.
app/sep/db/seed.py Seeds app-owned periodic schedules only when the owning app contributes a Celery module path; refactors report schedules into a helper.
tests/app/sep/test_config.py Adds coverage for the celery_module_path three-state behavior, including override validation and opt-out.
tests/app/sep/apps/framework/test_registry.py Adds tests for registry-derived celery module lists and include composition.
tests/app/sep/db/test_seed.py Adds tests ensuring schedules are omitted when a plugin is absent or opts out of Celery.
tests/app/sep/test_celery_registration.py Extends invariant tests to assert include/seed prefixes derive from the registry.
changelog.d/SEP-1551.changed.md Documents the behavioral change for Celery include list and seed prefix derivation.

Comment thread tests/app/sep/test_config.py Outdated
Comment thread app/sep/apps/framework/registry.py Outdated
Address PR review: build_celery_include() now dedupes while preserving
first-seen order so an app module colliding with the static base is
dropped. Correct the test docstring to reference App.celery_module_path.
@marcuscruz-percona marcuscruz-percona added the qa passed Tests for this PR are completed and successful. label Jul 14, 2026
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  app
  celery.py
  main.py
  app/core/celery
  config.py
  app/sep
  config.py 221
  inventory.py
  app/sep/apps/framework
  registry.py
  app/sep/apps/mysql_backups/restore
  deps.py
  app/sep/db
  seed.py 116-130
  app/sep/sync/syncers
  pmm.py
Project Total  

This report was generated by python-coverage-comment-action

@yyyyyyyan yyyyyyyan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcuscruz-percona — solid refactor. build_celery_include gives the include list one derivation that both app/celery.py and start_celery_worker compose, the test_configured_include_is_the_derived_single_source / test_app_owned_seed_prefixes_track_registry_modules invariants pin the seed↔include↔registration contract structurally, and the new App.celery_module_path three-state field faithfully mirrors api_router_path — the explicit-override branch even adds a fail-fast filesystem probe the router field defers to startup. The circular-re-entry deviation is clearly flagged in the description and the reasoning holds: nothing reads settings.CELERY.include before app.celery reassigns it. Validator ordering, path arithmetic, and the None-prefixed-task_name guard rails all check out.

Three Minor, non-blocking notes inline:

  • AppRegistry.celery_module_paths looks unused by production — every consumer calls the standalone helpers, never the registry property.
  • The on-disk module-existence probe is duplicated verbatim between the two config.py validators.
  • The _alerts_plugin_enabled / _report_plugin_enabled gates in the seed are redundant with app_celery_module_for(...) and inconsistent with the snippets path.

Nothing blocking — approving. Happy to re-review if you rework any of these.

Comment thread app/sep/apps/framework/registry.py Outdated
Comment thread app/sep/config.py Outdated
Comment thread app/sep/db/seed.py Outdated
@marcuscruz-percona
marcuscruz-percona enabled auto-merge (squash) July 15, 2026 15:26
… stale seed flags

- Extract _module_or_package_exists helper shared by both config validators
- Drop unused AppRegistry.celery_module_paths property/param; standalone
  app_celery_module_paths remains the single source
- Gate alerts/report seed schedules on app_celery_module_for alone, removing
  import-time plugin-enabled flags that could go stale on runtime APPS changes
… stale seed flags

- Extract _module_or_package_exists helper shared by both config validators
- Drop unused AppRegistry.celery_module_paths property/param; standalone
  app_celery_module_paths remains the single source
- Gate alerts/report seed schedules on app_celery_module_for alone, removing
  import-time plugin-enabled flags that could go stale on runtime APPS changes
Comment thread app/sep/apps/framework/registry.py Outdated
Comment thread app/sep/config.py Outdated
@marcuscruz-percona
marcuscruz-percona enabled auto-merge (squash) July 15, 2026 16:22
@marcuscruz-percona
marcuscruz-percona merged commit f295797 into main Jul 15, 2026
17 checks passed
@marcuscruz-percona
marcuscruz-percona deleted the SEP-1551 branch July 15, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python qa passed Tests for this PR are completed and successful.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants