Created
July 26, 2012 13:17
-
-
Save yml/3181999 to your computer and use it in GitHub Desktop.
Background tasks to be run either by uwsgi, or directly if on dev server.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Background tasks to be run either by uwsgi, or directly if on dev server. | |
""" | |
import cPickle as pickle | |
import logging | |
from django.core.mail import send_mail | |
LOG = logging.getLogger(__name__) | |
HAS_UWSGI = False | |
TASKS = {} | |
# Filled in after successful uwsgi import. Needed for unit testing. | |
SPOOL_OK = 1 | |
SPOOL = lambda x: x | |
# | |
# Plumbing | |
# | |
def backstage_spooler(env): | |
"""uwsgi spooler function, called by uwsgi, runs background tasks. | |
http://projects.unbit.it/uwsgi/wiki/Spooler | |
""" | |
unpacked = pickle.loads(env["__task_kwargs"]) | |
target = TASKS[env["__task_name"]] | |
try: | |
target(**unpacked) | |
except: | |
LOG.exception("Exception calling task %s", env["__task_name"]) | |
raise | |
return SPOOL_OK | |
try: | |
import uwsgi # pylint: disable=F0401 | |
HAS_UWSGI = True | |
uwsgi.spooler = backstage_spooler | |
SPOOL_OK = uwsgi.SPOOL_OK | |
SPOOL = uwsgi.spool | |
except ImportError: | |
HAS_UWSGI = False | |
def task(func): | |
"""Decorator to run the wrapped func | |
- as a uwsgi spool if in uwsgi | |
- directly if not | |
""" | |
return utask(func) if HAS_UWSGI else func | |
def utask(func): | |
"""Decorator. Wraps a function to run as a uwsgi spool task. | |
Don't use this directly, use @task instead. | |
""" | |
def enqueue(**kwargs): | |
"""Ask the uwsgi spooler to run our task. | |
Wraps up the arguments in a pickle, to allow non-string kwargs. | |
""" | |
packed = pickle.dumps(kwargs) | |
params = {"__task_kwargs": packed, "__task_name": func.__name__} | |
SPOOL(params) | |
TASKS[func.__name__] = func | |
return enqueue | |
# | |
# Write your tasks here | |
# | |
# - Tasks can only use kwargs (not positional args) | |
# - All kwargs must be pickleable | |
# | |
@task | |
def task_email(subject=None, body=None, | |
from_email=None, recipient_user=None): | |
"""Start background task to send an email. | |
Putting email in a background task only makes sense if we use | |
a remote mail server. If the mail server is on our local machine, | |
socket connection will be as fast as memcached, no background needed. | |
""" | |
send_mail(subject, body, from_email, | |
recipient_list=[recipient_user], | |
fail_silently=False) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment