From f82e8fc4d137fa00bac086e7b85034a613c7e559 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Tue, 13 Nov 2012 16:12:27 -0500 Subject: [PATCH] Move Markdown rendering out of the Tornado server (imported from commit fc726939aa1061c40b292899dbbc9ade3b29ea01) --- zephyr/models.py | 19 ++++++++++++++++--- zephyr/views.py | 7 +++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/zephyr/models.py b/zephyr/models.py index 9f93181062..98cdae1318 100644 --- a/zephyr/models.py +++ b/zephyr/models.py @@ -379,6 +379,14 @@ class Message(models.Model): @cache_with_key(lambda self, apply_markdown: 'message_dict:%d:%d' % (self.id, apply_markdown)) def to_dict(self, apply_markdown): + # Messages arrive in the Tornado process with the dicts already rendered. + # This avoids running the Markdown parser and some database queries in the single-threaded + # Tornado server. + # + # This field is not persisted to the database and will disappear if the object is re-fetched. + if hasattr(self, 'precomputed_dicts'): + return self.precomputed_dicts['text/html' if apply_markdown else 'text/x-markdown'] + obj = dict( id = self.id, sender_email = self.sender.user.email, @@ -481,10 +489,15 @@ def do_send_message(message, no_log=False): # We can only publish messages to longpolling clients if the Tornado server is running. if settings.TORNADO_SERVER: + # Render Markdown etc. here, so that the single-threaded Tornado server doesn't have to. + # TODO: Reduce duplication in what we send. + rendered = { 'text/html': message.to_dict(apply_markdown=True), + 'text/x-markdown': message.to_dict(apply_markdown=False) } requests.post(settings.TORNADO_SERVER + '/notify_new_message', data=[ - ('secret', settings.SHARED_SECRET), - ('message', message.id), - ('users', ','.join(str(user.id) for user in recipients))]) + ('secret', settings.SHARED_SECRET), + ('message', message.id), + ('rendered', simplejson.dumps(rendered)), + ('users', ','.join(str(user.id) for user in recipients))]) class Subscription(models.Model): user_profile = models.ForeignKey(UserProfile) diff --git a/zephyr/views.py b/zephyr/views.py index be47e6a774..8e24665616 100644 --- a/zephyr/views.py +++ b/zephyr/views.py @@ -647,6 +647,13 @@ def notify_new_message(request): for user in request.POST['users'].split(',')] message = Message.objects.get(id=request.POST['message']) + # Cause message.to_dict() to return the dicts already rendered in the other process. + # + # We decode this JSON only to eventually re-encode it as JSON. + # This isn't trivial to fix, because we do access some fields in the meantime + # (see send_with_safety_check). It's probably not a big deal. + message.precomputed_dicts = simplejson.loads(request.POST['rendered']) + for user in users: user.receive(message)