Dispatcharr/dispatcharr
R3XCHRIS f38d3a4f17 fix: register plugin @shared_tasks on worker startup (#1244)
Plugins live in /data/plugins/<slug>/plugin.py, outside INSTALLED_APPS,
so celery's autodiscover_tasks() never imports them. Any plugin using
module-level @shared_task for cron-scheduled work therefore has its
task unregistered with the worker after every worker restart, until
something else (a connect/utils.trigger_event call, etc.) lazily
imports the plugin module via PluginManager.discover_plugins.

In the meantime, beat fires the periodic task on time and the worker
rejects it:

  ERROR celery.worker.consumer.consumer Received unregistered task of
  type 'telegram_alerts.send_daily_report'.

PeriodicTask.last_run_at advances anyway, so the failure is silent at
the default INFO log level.

Fix: hook celery's worker_ready signal in dispatcharr/celery.py to
call PluginManager.discover_plugins(sync_db=False) on every worker
boot. Importing the plugin modules runs their @shared_task decorators,
registering the tasks before beat starts firing.

Exception handling is intentionally broad: if one plugin's plugin.py
has an import error, the worker must still come up — discovery failure
should not be a fatal error for the whole worker process.

Tests in tests/test_celery_plugin_discovery.py verify:
  - the handler calls discover_plugins(sync_db=False)
  - the handler swallows PluginManager.get() exceptions
  - the handler swallows discover_plugins() exceptions
  - the handler is actually connected to the worker_ready signal
Confirmed the test fails against current dev with the exact
'cannot import name discover_plugins_on_worker_ready' that motivates
this change, and passes with the fix.
2026-05-13 17:00:31 +01:00
..
__init__.py Initial commit 2025-02-18 11:14:09 -06:00
admin.py Alpha v3 2025-02-21 15:31:59 -06:00
app_initialization.py Enhancement: Refactored app initialization to prevent redundant execution across multiple worker processes. Created dispatcharr.app_initialization utility module with should_skip_initialization() function that prevents custom initialization tasks (backup scheduler sync, developer notifications sync) from running during management commands, in worker processes, or in development servers. This significantly reduces startup overhead in multi-worker deployments (e.g., uWSGI with 10 workers now syncs the scheduler once instead of 10 times). Applied to both CoreConfig and BackupsConfig apps. 2026-02-05 13:48:01 -06:00
asgi.py websockets behind auth, cleaned up errors and bad state handling in websocket.jsx 2025-05-10 08:40:53 -04:00
celery.py fix: register plugin @shared_tasks on worker startup (#1244) 2026-05-13 17:00:31 +01:00
consumers.py Enhancement: Initial fmp4 support and major ts_proxy refactor 2026-05-08 17:46:47 -05:00
jwt_ws_auth.py Enhance JWT authentication error handling and user redirection on token issues. 2025-05-15 14:12:31 -05:00
persistent_lock.py merged in dev 2026-03-26 12:17:43 -04:00
routing.py Websockets, fixed channel name collision, added back in multi-stream per channel support 2025-03-05 17:04:43 -05:00
settings.py Enhancement: Initial fmp4 support and major ts_proxy refactor 2026-05-08 17:46:47 -05:00
urls.py Enhancement: Initial fmp4 support and major ts_proxy refactor 2026-05-08 17:46:47 -05:00
utils.py refactor: Clean up get_client_ip() function in utils.py 2026-05-09 09:48:53 -05:00
wsgi.py Revert "fix(wsgi): ensure gevent monkey-patching before Django import chain" 2026-03-03 15:33:55 -06:00