Browse Source

Merge pull request #390 from sh4nks/unregister-celery-tasks

Don't register celery tasks for disabled plugins
Peter Justin 7 years ago
parent
commit
46b585ccbf
2 changed files with 53 additions and 42 deletions
  1. 39 33
      flaskbb/app.py
  2. 14 9
      flaskbb/plugins/manager.py

+ 39 - 33
flaskbb/app.py

@@ -8,58 +8,55 @@
     :copyright: (c) 2014 by the FlaskBB Team.
     :license: BSD, see LICENSE for more details.
 """
-import os
 import logging
 import logging.config
+import os
 import sys
 import time
 from functools import partial
 
+from flask import Flask, request
+from flask_login import current_user
 from sqlalchemy import event
 from sqlalchemy.engine import Engine
 from sqlalchemy.exc import OperationalError, ProgrammingError
-from flask import Flask, request
-from flask_login import current_user
 
-from flaskbb._compat import string_types, iteritems
-# views
-from flaskbb.user.views import user
-from flaskbb.message.views import message
+from flaskbb._compat import iteritems, string_types
 from flaskbb.auth.views import auth
-from flaskbb.management.views import management
-from flaskbb.forum.views import forum
-# models
-from flaskbb.user.models import User, Guest
 # extensions
 from flaskbb.extensions import (alembic, allows, babel, cache, celery, csrf,
                                 db, debugtoolbar, limiter, login_manager, mail,
                                 redis_store, themes, whooshee)
-
+from flaskbb.forum.views import forum
+from flaskbb.management.views import management
+from flaskbb.message.views import message
+from flaskbb.plugins import spec
+from flaskbb.plugins.manager import FlaskBBPluginManager
+from flaskbb.plugins.models import PluginRegistry
+from flaskbb.plugins.utils import remove_zombie_plugins_from_db, template_hook
+# models
+from flaskbb.user.models import Guest, User
+# views
+from flaskbb.user.views import user
 # various helpers
-from flaskbb.utils.helpers import (time_utcnow, format_date, time_since,
-                                   crop_title, is_online, mark_online,
-                                   forum_is_unread, topic_is_unread,
-                                   render_template, render_markup,
-                                   app_config_from_env, get_flaskbb_config,
-                                   get_alembic_locations)
-from flaskbb.utils.translations import FlaskBBDomain
+from flaskbb.utils.helpers import (app_config_from_env, crop_title,
+                                   format_date, forum_is_unread,
+                                   get_alembic_locations, get_flaskbb_config,
+                                   is_online, mark_online, render_markup,
+                                   render_template, time_since, time_utcnow,
+                                   topic_is_unread)
 # permission checks (here they are used for the jinja filters)
-from flaskbb.utils.requirements import (IsAdmin, IsAtleastModerator,
-                                        CanBanUser, CanEditUser,
-                                        TplCanModerate, TplCanDeletePost,
+from flaskbb.utils.requirements import (CanBanUser, CanEditUser, IsAdmin,
+                                        IsAtleastModerator, TplCanDeletePost,
                                         TplCanDeleteTopic, TplCanEditPost,
-                                        TplCanPostTopic, TplCanPostReply)
+                                        TplCanModerate, TplCanPostReply,
+                                        TplCanPostTopic)
 # whooshees
-from flaskbb.utils.search import (PostWhoosheer, TopicWhoosheer,
-                                  ForumWhoosheer, UserWhoosheer)
+from flaskbb.utils.search import (ForumWhoosheer, PostWhoosheer,
+                                  TopicWhoosheer, UserWhoosheer)
 # app specific configurations
 from flaskbb.utils.settings import flaskbb_config
-
-from flaskbb.plugins.models import PluginRegistry
-from flaskbb.plugins.manager import FlaskBBPluginManager
-from flaskbb.plugins.utils import remove_zombie_plugins_from_db, template_hook
-from flaskbb.plugins import spec
-
+from flaskbb.utils.translations import FlaskBBDomain
 
 logger = logging.getLogger(__name__)
 
@@ -151,8 +148,6 @@ def configure_celery_app(app, celery):
     TaskBase = celery.Task
 
     class ContextTask(TaskBase):
-        abstract = True
-
         def __call__(self, *args, **kwargs):
             with app.app_context():
                 return TaskBase.__call__(self, *args, **kwargs)
@@ -452,3 +447,14 @@ def load_plugins(app):
         if app.config["REMOVE_DEAD_PLUGINS"]:
             removed = remove_zombie_plugins_from_db()
             logger.info("Removed Plugins: {}".format(removed))
+
+    # we need a copy of it because of
+    # RuntimeError: dictionary changed size during iteration
+    tasks = celery.tasks.copy()
+    disabled_plugins = [
+        p.__package__ for p in app.pluggy.get_disabled_plugins()
+    ]
+    for task_name, task in iteritems(tasks):
+        if task.__module__.split(".")[0] in disabled_plugins:
+            logger.debug("Unregistering task: '{}'".format(task))
+            celery.tasks.unregister(task_name)

+ 14 - 9
flaskbb/plugins/manager.py

@@ -10,10 +10,10 @@
 """
 import logging
 
+import pluggy
 from pkg_resources import (DistributionNotFound, VersionConflict,
                            iter_entry_points)
 
-import pluggy
 from flaskbb.utils.helpers import parse_pkg_metadata
 
 logger = logging.getLogger(__name__)
@@ -29,7 +29,7 @@ class FlaskBBPluginManager(pluggy.PluginManager):
             project_name=project_name, implprefix=implprefix
         )
         self._plugin_metadata = {}
-        self._disabled_plugins = []
+        self._disabled_plugins = {}
 
         # we maintain a seperate dict for flaskbb.* internal plugins
         self._internal_name2plugin = {}
@@ -99,12 +99,6 @@ class FlaskBBPluginManager(pluggy.PluginManager):
             if self.get_plugin(ep.name):
                 continue
 
-            if self.is_blocked(ep.name):
-                self._disabled_plugins.append((ep.name, ep.dist))
-                self._plugin_metadata[ep.name] = \
-                    parse_pkg_metadata(ep.dist.key)
-                continue
-
             try:
                 plugin = ep.load()
             except DistributionNotFound:
@@ -115,6 +109,13 @@ class FlaskBBPluginManager(pluggy.PluginManager):
                 raise pluggy.PluginValidationError(
                     "Plugin %r could not be loaded: %s!" % (ep.name, e)
                 )
+
+            if self.is_blocked(ep.name):
+                self._disabled_plugins[plugin] = (ep.name, ep.dist)
+                self._plugin_metadata[ep.name] = \
+                    parse_pkg_metadata(ep.dist.key)
+                continue
+
             self.register(plugin, name=ep.name)
             self._plugin_distinfo.append((plugin, ep.dist))
             self._plugin_metadata[ep.name] = parse_pkg_metadata(ep.dist.key)
@@ -143,4 +144,8 @@ class FlaskBBPluginManager(pluggy.PluginManager):
 
     def list_disabled_plugins(self):
         """Returns a name/distinfo tuple pairs of disabled plugins."""
-        return self._disabled_plugins
+        return self._disabled_plugins.values()
+
+    def get_disabled_plugins(self):
+        """Returns a list with disabled plugins."""
+        return self._disabled_plugins.keys()