Как использовать декоратор @shared_task для задач на основе классов
Как видно из документации, декоратор @shared_task
позволяет создавать задачи без какого-либо конкретного экземпляра приложения. В приведенных примерах показано, как украсить задачу, основанную на функциях.
Как украсить задачу на основе класса?
Ответы
Ответ 1
Цитата Спросите у пользователя сельдерей-пользователей, где он объяснил разницу между @task a @shared_task. Вот ссылка на поток
TL; DR; @shared_task создаст независимый экземпляр задачи для каждого приложения, делая задачу повторно используемой.
Существует разница между @task (shared = True) и @shared_task
Дефрагментатор задач по умолчанию будет делиться задачами между приложениями, чтобы:
app1 = Celery()
@app1.task
def test():
pass
app2 = Celery()
тестовая задача будет зарегистрирована в обоих приложениях:
assert app1.tasks[test.name]
assert app2.tasks[test.name]
Однако имя 'test всегда будет ссылаться на экземпляр, связанный с' app1
приложение, поэтому оно будет настроено с помощью конфигурации app1s:
assert test.app is app1
Декодер @shared_task возвращает прокси-сервер, который всегда использует экземпляр задачи
в current_app:
app1 = Celery()
@shared_task
def test():
pass
assert test.app is app1
app2 = Celery()
assert test.app is app2
Это делает декоратор @shared_task полезным для библиотек и многоразовых приложений,
поскольку у них не будет доступа к приложению пользователя.
Кроме того, стандартный проект Django определяет экземпляр приложения
в рамках проекта Django:
из приложения импорта proj.celery
и нет смысла, чтобы приложение для повторного использования Django зависело от модуля проекта,
так как тогда он больше не будет использоваться повторно.
Ответ 2
В документации, на которую вы ссылаетесь, говорится:
Декодер @shared_task позволяет создавать задачи без конкретного экземпляра приложения:
Насколько я могу судить, документация вводит в заблуждение и должна сказать:
Декодер @shared_task позволяет создавать задачи, которые могут использоваться любыми приложениями.
Фактически, любая задача должна быть прикреплена к экземпляру приложения. Мои данные получены из исходного файла сельдерея celery/app/builtins.py
:
def shared_task(constructor):
"""Decorator that specifies a function that generates a built-in task.
The function will then be called for every new app instance created
(lazily, so more exactly when the task registry for that app is needed).
The function must take a single ``app`` argument.
"""
_shared_tasks.add(constructor)
return constructor
Итак, похоже, что вы можете использовать этот декоратор для создания задачи без конкретного экземпляра приложения, но на самом деле украшенная функция ДОЛЖНА принять аргумент приложения - как говорится в комментарии к источнику.
Следующая функция:
def load_shared_tasks(app):
"""Create built-in tasks for an app instance."""
constructors = set(_shared_tasks)
for constructor in constructors:
constructor(app)
Здесь вы можете подтвердить, что каждая функция, украшенная @shared_tasks
, будет вызываться с аргументом app
.