Skip to content

Instantly share code, notes, and snippets.

@yml
Created July 26, 2012 13:17
Show Gist options
  • Save yml/3181999 to your computer and use it in GitHub Desktop.
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.
"""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