Repository navigation
Defer startup command sync to post_migrate and a management command - #12
Merged
Merged
Conversation
AppConfig.ready() ran sync_registered_commands() and sync_declarative_schedules() during django.setup(), explicitly suppressing Django's "Accessing the database during app initialization" warning. With gunicorn --preload and pooled connections (psycopg3 pool), the master opened the pool pre-fork; forked workers inherited a pool whose background threads died at fork and wedged in getconn() — proven staging outage (2026-10-05). ready() now only populates the in-memory registry and connects a post_migrate receiver. Rows materialize when migrate finishes and via the new admin_runner_sync management command (manual runs, worker boot, re-sync after code changes). ADMIN_RUNNER_SYNC_ON_READY=True (default False) restores the legacy ready()-time sync for consumers that cannot run migrations during deploy.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
AppConfig.ready()executedsync_registered_commands()+sync_declarative_schedules()duringdjango.setup()(suppressing Django's own "Accessing the database during app initialization" warning). With gunicorn--preload+ psycopg3 pooled connections, the master opened the pool pre-fork and forked workers wedged ingetconn()— proven staging outage (2026-10-05). Independently, DB access during app init is against Django best practice and broke DB-less boots likecollectstaticin image builds.Changes
ready()now only runsautodiscover_commands()(import-time registry work, no DB) and connects apost_migratereceiver; no warning suppression, no blanketexcept.post_migrate(exactly once per migrate — the signal fires per installed app, so the receiver filters on the app config label) and via the newpython manage.py admin_runner_synccommand (manual runs, worker boot, re-sync after code changes). Both route through the newsync_all()orchestrator;OperationalErrortolerance is kept.ADMIN_RUNNER_SYNC_ON_READY = True(defaultFalse) restores the legacy ready()-time sync for consumers that cannot run migrations during deploy.command-sync-on-startup/declarative-schedulesspecs rewritten for the new behavior.Testing
tests/test_app_config.py: ready() executes zero queries, opens no connection (connection_createdinstrumented), never calls the sync functions; post_migrate syncs for this app, ignores other apps, runs exactly once per signal round; end-to-endcall_command("migrate")materializes rows; opt-in setting restores ready()-sync.tests/test_sync_command.py: command syncs commands + declarative schedules, success output, idempotent.uv run --group test pytest— 370 passed (12 new).uv lock --locked,pre-commit run -a(ruff/format/prettier),pyright src— all green.Tested: full suite 370 passed; pre-commit + pyright + lock check green; draft opened for owner review (not merging).
Draft — leaving merge decision to the owner.