Wire up plugin discovery without hitting the DB during app init. - Skip during common management commands that don't need discovery. - Register post_migrate handler to sync plugin registry to DB after migrations. - Run in-memory discovery (no DB) in every non-Celery process
(self)
| 9 | verbose_name = "Plugins" |
| 10 | |
| 11 | def ready(self): |
| 12 | """Wire up plugin discovery without hitting the DB during app init. |
| 13 | |
| 14 | - Skip during common management commands that don't need discovery. |
| 15 | - Register post_migrate handler to sync plugin registry to DB after migrations. |
| 16 | - Run in-memory discovery (no DB) in every non-Celery process so plugin |
| 17 | modules are imported and monkey-patches apply. This includes uWSGI workers |
| 18 | under lazy-apps=true, which each start cold and never inherit a warmed fork. |
| 19 | Celery workers skip here and discover via the worker_ready signal instead. |
| 20 | - One-shot startup tasks (schedule setup, repo refresh) are gated by |
| 21 | should_skip_initialization() so they only fire in the master/main process. |
| 22 | """ |
| 23 | try: |
| 24 | # Allow explicit opt-out via env var |
| 25 | if os.environ.get("DISPATCHARR_SKIP_PLUGIN_AUTODISCOVERY", "").lower() in ("1", "true", "yes"): |
| 26 | return |
| 27 | |
| 28 | argv = sys.argv[1:] if len(sys.argv) > 1 else [] |
| 29 | mgmt_cmds_to_skip = { |
| 30 | # Skip immediate discovery for these commands |
| 31 | "makemigrations", "collectstatic", "check", "test", "shell", "showmigrations", |
| 32 | } |
| 33 | if argv and argv[0] in mgmt_cmds_to_skip: |
| 34 | return |
| 35 | |
| 36 | # Run discovery with DB sync after the plugins app has been migrated |
| 37 | def _post_migrate_discover(sender=None, app_config=None, **kwargs): |
| 38 | try: |
| 39 | if app_config and getattr(app_config, 'label', None) != 'plugins': |
| 40 | return |
| 41 | from .loader import PluginManager |
| 42 | PluginManager.get().discover_plugins(sync_db=True) |
| 43 | except Exception: |
| 44 | import logging |
| 45 | logging.getLogger(__name__).exception("Plugin discovery failed in post_migrate") |
| 46 | |
| 47 | post_migrate.connect( |
| 48 | _post_migrate_discover, |
| 49 | dispatch_uid="apps.plugins.post_migrate_discover", |
| 50 | ) |
| 51 | |
| 52 | from dispatcharr.app_initialization import should_skip_initialization |
| 53 | # Skip discovery for Celery (worker_ready signal handles it) and |
| 54 | # pure management commands that don't serve requests. Every other |
| 55 | # process - including each uWSGI worker under lazy-apps=true - runs |
| 56 | # discovery so plugin modules are imported and monkey-patches apply. |
| 57 | _no_discovery_cmds = {'celery', 'beat', 'migrate', 'dbshell', 'loaddata'} |
| 58 | if not any(cmd in sys.argv for cmd in _no_discovery_cmds): |
| 59 | from .loader import PluginManager |
| 60 | PluginManager.get().discover_plugins(sync_db=False) |
| 61 | |
| 62 | if should_skip_initialization(): |
| 63 | return |
| 64 | except Exception: |
| 65 | # Avoid breaking startup due to plugin errors |
| 66 | import logging |
| 67 | |
| 68 | logging.getLogger(__name__).exception("Plugin discovery wiring failed during app ready") |
nothing calls this directly
no test coverage detected