Celery+Django KeyError Незарегистрированная задача

Я близок к тому, чтобы заставить Celery работать с моим проектом Django + Docker-Compose, но у меня есть проблема, когда рабочий никогда не распознает поставленную перед ним задачу. Основная идея в том, что у меня есть функция insertIntoDatabase, которая вызывается из задачи:

myapp/tasks.py:

@task(name='tasks.db_ins')
def db_ins_task(datapoints, user, description):
    from utils.db.databaseinserter import insertIntoDatabase
    insertIntoDatabase(datapoints, user, description)

И в views.py я делаю:

from .tasks import db_ins_task
...
db_ins_task.delay(datapoints, user, description)

datapoints — это в основном список словарей, а user и description — просто строки. Проблема в том, что при запуске рабочего контейнера Celery эта db_ins_task никогда не обнаруживается как одна из перечисленных задач, поэтому, когда я пытаюсь загрузить что-либо на свой веб-сайт, я получаю следующую ошибку:

worker_1   | [2015-09-25 19:38:00,205: ERROR/MainProcess] Received unregistered task of type u'tasks.db_ins'.
worker_1   | The message has been ignored and discarded.
worker_1   | 
worker_1   | Did you remember to import the module containing this task?
worker_1   | Or maybe you are using relative imports?
worker_1   | Please see http://bit.ly/gLye1c for more information.
...
worker_1   | Traceback (most recent call last):
worker_1   |   File "/usr/local/lib/python2.7/site-packages/celery/worker/consumer.py", line 455, in on_task_received
worker_1   |     strategies[name](message, body,
worker_1   | KeyError: u'tasks.db_ins'

Я пытался заставить работника распознать задачу, включая добавление этого параметра в settings.py:

CELERY_IMPORTS = ('myapp.tasks',)

Я добавил журнал отладки в tasks.py, чтобы убедиться, что он не был полностью пропущен, и я могу подтвердить, что каждый раз, когда я пытаюсь запустить задачу, регистратор сообщает, что tasks.py выполняется. Для справки, вот контейнер worker в docker-compose.yml:

worker:
  build: .
  links:
    - redis
  command: bash -c "celery -A myproj worker --app=taskman.celery --loglevel=DEBUG"

celery.py находится в отдельном приложении под названием taskman. Что именно я делаю неправильно, что может вызвать эту ошибку с задачами?


person Dan K    schedule 25.09.2015    source источник
comment
Попробуйте добавить это в свой файл конфигурации app.autodiscover_tasks(lambda: settings.INSTALLED_APPS). Где приложение — это ваше приложение Celery.   -  person Gocht    schedule 25.09.2015
comment
Хм, это уже в моем celery.py. Именно здесь я получаю сельдерей, чтобы найти его настройки из settings.py моего проекта Django, и эта часть определенно работает, поскольку контейнер worker правильно использует эти настройки.   -  person Dan K    schedule 25.09.2015
comment
Попробуйте вызвать свой модуль следующим образом: ', ])   -  person Gocht    schedule 25.09.2015
comment
Есть ли причина делать это вместо использования settings.py? В celery.py у меня есть app.config_from_object('django.conf:settings'), который уже устанавливает такие вещи, как брокер, серверная часть и включение. Также localhost не будет работать, поскольку брокер/бэкенд Redis представляет собой контейнер с другим IP-адресом.   -  person Dan K    schedule 25.09.2015
comment
В моем файле конфигурации сельдерея мне пришлось использовать конфигурацию, которую я дал вам выше. Это в документах.   -  person Gocht    schedule 25.09.2015
comment
Я уже делаю ту же конфигурацию, хотя. Это уже в settings.py. Я знаю, что это работает, потому что журналы для celery worker показывают правильный IP-адрес контейнера Redis для брокера и серверной части. Проблема должна быть в другом. Может быть, у вас есть другие идеи?   -  person Dan K    schedule 25.09.2015


Ответы (1)


В вашем вопросе вы показываете запуск своего работника с помощью:

celery -A myproj worker --app=taskman.celery --loglevel=DEBUG

Теперь проблема в том, что -A и --app означают одно и то же. Так что это говорит мне о том, что вы колебались между использованием myproj или taskman.celery в качестве держателя вашего приложения Celery. Ваш воркер использует taskman.celery, потому что при тестировании я обнаружил, что если какая-либо комбинация -A или --app задана одному вызову воркера, используется только последний из них.

При этом есть один способ представить вашу проблему. Если ваш файл myapp/tasks.py получает декоратор task из myproj.celery.app, а не из taskman.celery.app, вы регистрируете свои задачи не в том приложении.

person Louis    schedule 26.09.2015
comment
Это мне очень помогло, спасибо. Для более подробной информации, что сработало для меня, так это изменить команду на celery worker --app=myapp.tasks --loglevel=DEBUG. Я также избавился от name из декоратора. Также была ошибка о том, что задаче было передано слишком много аргументов, но удаление цветка, похоже, помогло (на самом деле я никогда не использовал цветок). - person Dan K; 27.09.2015