# HG changeset patch # User Ludovic Chabant # Date 1396157287 25200 # Node ID c6ec6096bd9509b7cfbf4ef2ff7e8026981b4e06 # Parent 8e3f8e34090f93918d710165ce0cd3906efc802c Simpler out-of-the-box support for background updates. Now by default Celery uses an SQLite broker, with storage in the `.wiki` directory. This makes it possible to support async updates by simply passing `--usetasks` to `wk runserver`, while also running `wk runtasks` in a different process. diff -r 8e3f8e34090f -r c6ec6096bd95 wikked/commands/web.py --- a/wikked/commands/web.py Fri Mar 28 23:33:00 2014 -0700 +++ b/wikked/commands/web.py Sat Mar 29 22:28:07 2014 -0700 @@ -1,4 +1,6 @@ import os +import os.path +import imp import logging from wikked.commands.base import WikkedCommand, register_command @@ -20,6 +22,11 @@ parser.add_argument('--port', help="The port to use", default=5000) + parser.add_argument('--usetasks', + help="Use background tasks for updating the wiki after a " + "page has been edited. You will have to run " + "`wk runtasks` at the same time as `wk runserver`.", + action='store_true') parser.add_argument('-d', '--dev', help="Use development mode. " "This makes Wikked use development assets (separate and " @@ -33,9 +40,15 @@ # TODO: make the Flask initialization more clever. os.chdir(ctx.params.root) + # Setup some settings that need to be set before the app is created. + import wikked.settings + if ctx.args.usetasks: + wikked.settings.WIKI_ASYNC_UPDATE = True + + # Create/import the app. from wikked.web import app - # Setup the app. + # Setup other simpler settings. if ctx.args.dev: app.config['DEV_ASSETS'] = True app.config['WIKI_AUTO_RELOAD'] = True @@ -53,3 +66,43 @@ use_debugger=debug_mode, use_reloader=debug_mode) + +@register_command +class RunTasksCommand(WikkedCommand): + def __init__(self): + super(RunTasksCommand, self).__init__() + self.name = 'runtasks' + self.description = "Runs the tasks to update the wiki in the background." + + def setupParser(self, parser): + pass + + def run(self, ctx): + # Import the Celery app and update its configuration with the same + # stuff as what the Flask app got. + from wikked.tasks import celery_app + + celery_app.conf.update(BROKER_URL='sqla+sqlite:///%(root)s/.wiki/broker.db') + config_path = os.path.join(ctx.params.root, '.wiki', 'app.cfg') + if os.path.isfile(config_path): + obj = self._loadConfig(config_path) + celery_app.conf.update(obj.__dict__) + celery_app.conf.BROKER_URL = celery_app.conf.BROKER_URL % ( + { 'root': ctx.params.root }) + + os.chdir(os.path.join(os.path.dirname(__file__), '..', '..')) + argv = ['celery', 'worker', '-A', 'wikked.tasks'] + if ctx.args.debug: + argv += ['-l', 'DEBUG'] + celery_app.start(argv) + + def _loadConfig(self, path): + d = imp.new_module('config') + d.__file__ = path + try: + with open(path) as config_file: + exec(compile(config_file.read(), path, 'exec'), d.__dict__) + except IOError as e: + e.strerror = 'Unable to load Flask/Celery configuration file (%s)' % e.strerror + raise + return d diff -r 8e3f8e34090f -r c6ec6096bd95 wikked/web.py --- a/wikked/web.py Fri Mar 28 23:33:00 2014 -0700 +++ b/wikked/web.py Sat Mar 29 22:28:07 2014 -0700 @@ -23,7 +23,7 @@ app.config.setdefault('UPDATE_WIKI_ON_START', True) app.config.setdefault('WIKI_AUTO_RELOAD', False) app.config.setdefault('WIKI_ASYNC_UPDATE', False) -app.config.setdefault('BROKER_URL', 'amqp://') +app.config.setdefault('BROKER_URL', 'sqla+sqlite:///%(root)s/.wiki/broker.db') # Find the wiki root, and further configure the app if there's a @@ -132,10 +132,14 @@ from wikked.tasks import celery_app, update_wiki # Configure Celery. + app.config['BROKER_URL'] = app.config['BROKER_URL'] % ( + { 'root': wiki_root }) celery_app.conf.update(app.config) + app.logger.debug("Using Celery broker: %s" % app.config['BROKER_URL']) # Make the wiki use the background update task. def async_updater(wiki): + app.logger.debug("Running update task on Celery.") update_wiki.delay(wiki.root) app.wiki_updater = async_updater