Как использовать декоратор @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.