diff --git a/dev-requirements.txt b/dev-requirements.txt index 7187845..bbfe2bb 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,4 +2,5 @@ wheel twine Django>=1.7,<1.10 -tornado>=3.2 \ No newline at end of file +tornado>=3.2 +celery>=3.1.23 \ No newline at end of file diff --git a/sparkpost/django/email_backend.py b/sparkpost/django/email_backend.py index 1e44a10..34c045b 100644 --- a/sparkpost/django/email_backend.py +++ b/sparkpost/django/email_backend.py @@ -4,6 +4,7 @@ from sparkpost import SparkPost from .message import SparkPostMessage +from .tasks import send_messages class SparkPostEmailBackend(BaseEmailBackend): @@ -37,3 +38,13 @@ def _send(self, message): params = getattr(settings, 'SPARKPOST_OPTIONS', {}).copy() params.update(message) return self.client.transmissions.send(**params) + + +class SparkPostCeleryEmailBackend(SparkPostEmailBackend): + def send_messages(self, email_messages): + """ + Send emails, returns celery result object (AsyncResult) + When task will be complete, it will contain integer + representing number of successful emails + """ + return send_messages.delay(self, email_messages) diff --git a/sparkpost/django/tasks.py b/sparkpost/django/tasks.py new file mode 100644 index 0000000..8aa800d --- /dev/null +++ b/sparkpost/django/tasks.py @@ -0,0 +1,32 @@ +from celery import chord +from celery.task import task + +from .message import SparkPostMessage + + +@task() +def send_messages(obj, email_messages): + """ + Celery task for 'send_messages' EmailBackend method. + It sends all email messages in parallel via 'send_message' task, + and then it reduces all results via `send_summary` task + (celery chord is convenient) + """ + return chord(send_message.s(obj, email_message) + for email_message in email_messages)(send_summary.s()) + + +@task() +def send_message(obj, message): + try: + response = obj._send(SparkPostMessage(message)) + except Exception: + if not obj.fail_silently: + raise + else: + return response['total_accepted_recipients'] + + +@task() +def send_summary(send_results): + return sum([send_result for send_result in send_results]) diff --git a/tox.ini b/tox.ini index db71c33..30e6846 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = {py27,py34}-django{17,18}, py35-django{18,19} +envlist = {py27,py34}-django{17,18}-celery, py35-django{18,19}-celery [testenv] deps = @@ -7,10 +7,11 @@ deps = django17: Django>=1.7,<1.8 django18: Django>=1.8,<1.9 django19: Django>=1.9,<1.10 + celery: celery==3.1.23 commands = py.test test/ -[testenv:py35-django19] +[testenv:py35-django19-celery] commands = flake8 sparkpost test