Skip to content

Commit

Permalink
Upgrade of celery to 4.0, removed djcelery as it's no longer maintained
Browse files Browse the repository at this point in the history
  • Loading branch information
Mathieu Hinderyckx authored and bameda committed Nov 28, 2016
1 parent ff919ae commit ac9b2ee
Show file tree
Hide file tree
Showing 37 changed files with 266 additions and 318 deletions.
26 changes: 2 additions & 24 deletions .travis.yml
Expand Up @@ -13,32 +13,14 @@ env:
- DJANGO="Django>=1.10,<1.11"
- DJANGO="Django>=1.9,<1.10"
- DJANGO="Django>=1.8,<1.9"
- DJANGO="Django>=1.7,<1.8"
- DJANGO="Django>=1.6,<1.7"
- DJANGO="Django>=1.5,<1.6"
- DJANGO="Django>=1.4,<1.5"
- DJANGO="https://github.com/django/django/archive/master.tar.gz"

matrix:
exclude:
- python: "3.5"
env: DJANGO="Django>=1.7,<1.8"
- python: "3.5"
env: DJANGO="Django>=1.6,<1.7"
- python: "3.5"
env: DJANGO="Django>=1.5,<1.6"
- python: "3.5"
env: DJANGO="Django>=1.4,<1.5"

- python: "3.4"
env: DJANGO="Django>=1.4,<1.5"

- python: "3.3"
env: DJANGO="Django>=1.10,<1.11"
- python: "3.3"
env: DJANGO="Django>=1.9,<1.10"
- python: "3.3"
env: DJANGO="Django>=1.4,<1.5"
- python: "3.3"
env: DJANGO="https://github.com/django/django/archive/master.tar.gz"
allow_failures:
Expand All @@ -47,15 +29,11 @@ matrix:
install:
- travis_retry pip install $DJANGO
- travis_retry pip install psycopg2==2.6.1
- travis_retry pip install django-celery==3.1.17
- travis_retry pip install celery==3.1.24
- travis_retry pip install celery==4.0.0
- travis_retry pip install futures # For python 2.7

services:
- postgresql

before_script:
- createdb test

script:
- python runtests.py
- python -Wall runtests.py
2 changes: 1 addition & 1 deletion AUTHORS.md
Expand Up @@ -15,6 +15,6 @@ generally made djmail that much better:
- David Fischer <david.fischer.ch@gmail.com>
- Jesús Espino <jespinog@gmail.com>
- Kirill Klenov <horneds@gmail.com>
- Mathieu Hinderyckx
- Mathieu Hinderyckx <mathieu.hinderyckx@gmail.com>
- Mauricio de Abreu Antunes <mauricio.abreua@gmail.com>

2 changes: 2 additions & 0 deletions djmail/__init__.py
@@ -1 +1,3 @@
# -*- encoding: utf-8 -*-

default_app_config = 'djmail.apps.DjMailConfig'
6 changes: 3 additions & 3 deletions djmail/admin.py
Expand Up @@ -4,12 +4,12 @@

from django.contrib import admin

from . import models
from .models import Message


@admin.register(Message)
class MessageAdmin(admin.ModelAdmin):
list_display = ['uuid', 'from_email', 'to_email', 'status', 'priority', 'created_at', 'sent_at', 'retry_count']
list_filter = ['status', 'priority', 'created_at', 'sent_at', 'retry_count']
search_fields = ['from_email', 'to_email', 'subject', 'uuid']

admin.site.register(models.Message, MessageAdmin)
date_hierarchy = 'created_at'
10 changes: 10 additions & 0 deletions djmail/apps.py
@@ -0,0 +1,10 @@
from django.apps import AppConfig


class DjMailConfig(AppConfig):
name = 'djmail'
verbose_name = "DjMail"

def ready(self):
from . import signals
super(DjMailConfig, self).ready()
4 changes: 3 additions & 1 deletion djmail/backends/async.py
Expand Up @@ -19,6 +19,7 @@ def _close_connection_on_finish(function):
Decorator for future task, that closes
Django database connection when it ends.
"""

@functools.wraps(function)
def _decorator(*args, **kwargs):
try:
Expand All @@ -34,6 +35,7 @@ class EmailBackend(base.BaseEmailBackend):
Asynchronous email back-end that uses a
thread pool for sending emails.
"""

def send_messages(self, email_messages):
if len(email_messages) == 0:
future = Future()
Expand All @@ -42,6 +44,6 @@ def send_messages(self, email_messages):

@_close_connection_on_finish
def _send(messages):
return core._send_messages(email_messages)
return core._send_messages(messages)

return executor.submit(_send, email_messages)
1 change: 1 addition & 0 deletions djmail/backends/base.py
Expand Up @@ -8,6 +8,7 @@ class BaseEmailBackend(object):
Base class that implements a Django
mail back-end interface.
"""

def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
Expand Down
1 change: 1 addition & 0 deletions djmail/backends/celery.py
Expand Up @@ -14,6 +14,7 @@ class EmailBackend(base.BaseEmailBackend):
Asynchronous email back-end that uses
Celery task for sending emails.
"""

def send_messages(self, email_messages):
if len(email_messages) == 0:
return 0
Expand Down
1 change: 1 addition & 0 deletions djmail/backends/default.py
Expand Up @@ -11,6 +11,7 @@ class EmailBackend(base.BaseEmailBackend):
Default email back-end that sends e-mails
synchronously.
"""

def send_messages(self, email_messages):
if len(email_messages) == 0:
return 0
Expand Down
32 changes: 17 additions & 15 deletions djmail/core.py
Expand Up @@ -11,9 +11,10 @@
from django.core.mail import get_connection
from django.core.paginator import Paginator
from django.utils import timezone
StringIO = io.BytesIO if sys.version_info[0] == 2 else io.StringIO

from . import models
from .models import Message

StringIO = io.BytesIO if sys.version_info[0] == 2 else io.StringIO

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -50,10 +51,10 @@ def _safe_send_message(message_model, connection):
logger.error(message_model.exception)
else:
if sended == 1:
message_model.status = models.STATUS_SENT
message_model.status = Message.STATUS_SENT
message_model.sent_at = timezone.now()
else:
message_model.status = models.STATUS_FAILED
message_model.status = Message.STATUS_FAILED
message_model.retry_count += 1

message_model.save()
Expand All @@ -62,8 +63,7 @@ def _safe_send_message(message_model, connection):

def _get_real_backend():
real_backend_path = getattr(
settings,
'DJMAIL_REAL_BACKEND',
settings, 'DJMAIL_REAL_BACKEND',
'django.core.mail.backends.console.EmailBackend')
return get_connection(backend=real_backend_path, fail_silently=False)

Expand All @@ -73,18 +73,20 @@ def _send_messages(email_messages):

# Create a messages on a database for correct
# tracking of their status.
email_models = [models.Message.from_email_message(email, save=True)
for email in email_messages]
email_models = [
Message.from_email_message(
email, save=True) for email in email_messages
]

# Open connection for send all messages
connection.open()
try:
sended_counter = 0
for email, model_instance in zip(email_messages, email_models):
if hasattr(email, "priority"):
if email.priority <= models.PRIORITY_LOW:
if email.priority <= Message.PRIORITY_LOW:
model_instance.priority = email.priority
model_instance.status = models.STATUS_PENDING
model_instance.status = Message.STATUS_PENDING
model_instance.save()
sended_counter += 1
continue
Expand All @@ -99,7 +101,7 @@ def _send_pending_messages():
"""
Send pending, low priority messages.
"""
queryset = models.Message.objects.filter(status=models.STATUS_PENDING)\
queryset = Message.objects.filter(status=Message.STATUS_PENDING)\
.order_by('-priority', 'created_at')
connection = _get_real_backend()
connection.open()
Expand All @@ -118,7 +120,7 @@ def _retry_send_messages():
Retry to send failed messages.
"""
max_retry_value = getattr(settings, 'DJMAIL_MAX_RETRY_NUMBER', 3)
queryset = models.Message.objects.filter(status=models.STATUS_FAILED)\
queryset = Message.objects.filter(status=Message.STATUS_FAILED)\
.filter(retry_count__lte=max_retry_value)\
.order_by('-priority', 'created_at')

Expand All @@ -139,6 +141,6 @@ def _mark_discarded_messages():
limit and marks them as discarded.
"""
max_retry_value = getattr(settings, 'DJMAIL_MAX_RETRY_NUMBER', 3)
queryset = models.Message.objects.filter(status=models.STATUS_FAILED,
retry_count__gt=max_retry_value)
return queryset.update(status=models.STATUS_DISCARDED)
queryset = Message.objects.filter(
status=Message.STATUS_FAILED, retry_count__gt=max_retry_value)
return queryset.update(status=Message.STATUS_DISCARDED)
11 changes: 6 additions & 5 deletions djmail/management/commands/djmail_delete_old_messages.py
Expand Up @@ -2,7 +2,7 @@

from datetime import datetime, timedelta
from django.core.management.base import BaseCommand
from djmail import models
from djmail.models import Message


class Command(BaseCommand):
Expand All @@ -12,9 +12,10 @@ def add_arguments(self, parser):
parser.add_argument(
'--days',
type=int,
default=183, # default = 6 months
help='Number of days to use as cut-off for deletion',
)
default=183, # default = 6 months
help='Number of days to use as cut-off for deletion')

def handle(self, *args, **options):
models.Message.objects.filter(sent_at__lt=datetime.now() - timedelta(days=options['days']), status=models.STATUS_SENT).delete()
Message.objects.filter(
sent_at__lt=datetime.now() - timedelta(days=options['days']),
status=Message.STATUS_SENT).delete()
24 changes: 24 additions & 0 deletions djmail/migrations/0002_auto_20161118_1347.py
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2016-11-18 13:47
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('djmail', '0001_initial'),
]

operations = [
migrations.AlterModelOptions(
name='message',
options={'ordering': ['-created_at'], 'verbose_name': 'Message', 'verbose_name_plural': 'Messages'},
),
migrations.AlterField(
model_name='message',
name='priority',
field=models.SmallIntegerField(choices=[(20, 'Low'), (50, 'Standard')], default=50),
),
]
39 changes: 15 additions & 24 deletions djmail/models.py
Expand Up @@ -2,31 +2,27 @@

from __future__ import unicode_literals

import uuid

from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver

from . import utils


STATUS_DRAFT = 10
STATUS_PENDING = 20
STATUS_SENT = 30
STATUS_FAILED = 40
STATUS_DISCARDED = 50

PRIORITY_LOW = 20
PRIORITY_STANDARD = 50


class Message(models.Model):
STATUS_DRAFT = 10
STATUS_PENDING = 20
STATUS_SENT = 30
STATUS_FAILED = 40
STATUS_DISCARDED = 50
STATUS_CHOICES = (
(STATUS_DRAFT, 'Draft'),
(STATUS_SENT, 'Sent'),
(STATUS_FAILED, 'Failed'),
(STATUS_DISCARDED, 'Discarded'),
(STATUS_DISCARDED, 'Discarded'), )
PRIORITY_LOW = 20
PRIORITY_STANDARD = 50
PRIORITY_CHOICES = (
(PRIORITY_LOW, 'Low'),
(PRIORITY_STANDARD, 'Standard'),
)

uuid = models.CharField(max_length=40, primary_key=True)
Expand All @@ -41,7 +37,7 @@ class Message(models.Model):

retry_count = models.SmallIntegerField(default=-1)
status = models.SmallIntegerField(choices=STATUS_CHOICES, default=STATUS_DRAFT)
priority = models.SmallIntegerField(default=PRIORITY_STANDARD)
priority = models.SmallIntegerField(choices=PRIORITY_CHOICES, default=PRIORITY_STANDARD)

created_at = models.DateTimeField(auto_now_add=True)
sent_at = models.DateTimeField(null=True, default=None)
Expand All @@ -61,7 +57,8 @@ def get_body_key(body_type):
"to_email": ",".join(utils.force_text(x) for x in email_message.to),
"subject": utils.force_text(email_message.subject),
"data": utils.serialize_email_message(email_message),
get_body_key(email_message.content_subtype): utils.force_text(email_message.body)
get_body_key(email_message.content_subtype):
utils.force_text(email_message.body)
}

# Update the body (if missing) from the alternatives
Expand All @@ -75,12 +72,6 @@ def get_body_key(body_type):
return instance

class Meta:
ordering = ['created_at']
ordering = ['-created_at']
verbose_name = 'Message'
verbose_name_plural = 'Messages'


@receiver(pre_save, sender=Message, dispatch_uid='message_uuid_signal')
def generate_uuid(sender, instance, **kwargs):
if not instance.uuid:
instance.uuid = str(uuid.uuid1())
14 changes: 14 additions & 0 deletions djmail/signals.py
@@ -0,0 +1,14 @@
# -*- encoding: utf-8 -*-

import uuid

from django.db.models.signals import pre_save
from django.dispatch import receiver

from .models import Message


@receiver(pre_save, sender=Message, dispatch_uid='message_uuid_signal')
def generate_uuid(sender, instance, **kwargs):
if not instance.uuid:
instance.uuid = str(uuid.uuid1())

0 comments on commit ac9b2ee

Please sign in to comment.