14.3.55. crate_anon.crateweb.consent.tasks
crate_anon/crateweb/consent/tasks.py
Copyright (C) 2015, University of Cambridge, Department of Psychiatry. Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
This file is part of CRATE.
CRATE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
CRATE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with CRATE. If not, see <https://www.gnu.org/licenses/>.
Celery tasks for the CRATE consent-to-contact system.
See also crate_anon.crateweb.consent.celery
, which defines the app
.
If you get a “received unregistered task” error:
Restart the Celery worker. That may fix it.
If that fails, consider: SPECIFY ABSOLUTE NAMES FOR TASKS. e.g. with
@shared_task(name="myfuncname")
. Possible otherwise that if this module is imported in different ways (e.g. absolute, relative), you’ll get a “Received unregistered task” error. https://docs.celeryq.org/en/latest/userguide/tasks.html#task-names
Acknowledgement/not doing things more than once:
https://docs.celeryproject.org/en/latest/userguide/tasks.html
default is to acknowledge on receipt of request, not after task completion; that prevents things from happening more than once. If you can guarantee your function is idempotent, you can acknowledge after completion.
https://docs.celeryproject.org/en/latest/faq.html#faq-acks-late-vs-retry
We’ll stick with the default (slightly less reliable but won’t be run more than once).
Circular imports:
https://stackoverflow.com/questions/17313532/django-import-loop-between-celery-tasks-and-my-models
The potential circularity is:
At launch, Celery must import tasks, which could want to import models.
At launch, Django loads models, which may use tasks.
Simplest solution is to keep tasks very simple (as below) and use delayed imports here.
Race condition:
Django:
existing object
amend with form
save()
call function.delay(obj.id)
Object is received by Celery in the state before save() at step 3.
https://celery.readthedocs.org/en/latest/userguide/tasks.html#database-transactions
SOLUTION: https://docs.djangoproject.com/en/dev/topics/db/transactions/#django.db.transaction.on_commit
from django.db import transaction transaction.on_commit(lambda: blah.delay(blah))
Requires Django 1.9. As of 2015-11-21, that means 1.9rc1