Предваряя мой вопрос тем фактом, что я новичок в Celery, и на это (1) мог быть дан ответ где-то еще (если это так, я не смог найти ответ) или (2) может быть лучший способ достичь моей цели чем то, о чем я прямо спрашиваю.
Кроме того, я знаю о celery.contrib.methods
, но task_method
не совсем соответствует тому, что я ищу.
Моя цель
Я хотел бы создать примесь класса, которая превращает весь класс в задачу Celery. Например, миксин, представленный чем-то вроде приведенного ниже кода (который сейчас не запускается):
from celery import Task
class ClassTaskMixin(Task):
@classmethod
def enqueue(cls, *args, **kwargs):
cls.delay(*args, **kwargs)
def run(self, *args, **kwargs):
Obj = type(self.name, (), {})
Obj(*args, **kwargs).run_now()
def run_now(self):
raise NotImplementedError()
В отличие от использования task_method
, я не хочу полностью создавать экземпляр класса до постановки задачи в очередь и вызова .delay()
. Скорее, я хочу просто передать имя класса вместе с любыми соответствующими параметрами инициализации асинхронному процессу. Затем асинхронный процесс полностью создаст экземпляр класса, используя имя класса и заданные параметры инициализации, а затем вызовет какой-либо метод (например, .run_now()
) для созданного объекта.
Пример использования
Создание и отправка электронной почты асинхронно может быть примером использования миксина, который мне нужен.
class WelcomeEmail(EmailBase, ClassTaskMixin):
def __init__(self, recipient_address, template_name, template_context):
self.recipient_address = recipient_address
self.template_name = template_name
self.template_context = template_context
def send(self):
self.render_templates()
self.construct_mime()
self.archive_to_db()
self.send_smtp_email()
def run_now(self):
self.send()
Приведенный выше код отправляет электронное письмо в асинхронном процессе Celery, вызывая WelcomeEmail.enqueue(recipient_address, template_name, template_context)
. Синхронная отправка электронной почты в процессе может быть выполнена вызовом WelcomeEmail(recipient_address, template_name, template_context).send()
.
Вопросы
- Есть ли причина того, что то, что я пытаюсь сделать, очень, очень неправильно в рамках Celery?
- Есть ли лучший способ структурировать миксин, чтобы сделать его более сельдерейным, чем то, что я предложил (лучшие имена атрибутов, другая структура методов и т. д.)?
- Чего мне не хватает, чтобы примесь работала в случае использования, как я описал?