Django model doesn't get saved to database inside Celery Task
Asked Answered
O

4

6

I've hit a really nasty situation. I have the following setup. I have a django model representing an FSM with a django FSM field

I have a celery task that sends out an email and then advances the state of the main objects FSM. From the celery task's perspective, the object "seems" to be saved. But from the main django process' perspective, the object isn't being updated. The strange thing is that ancillary objects are being saved properly to the DB, and later accessible from the main django process.

I explicitly call .save() on the object from the Celery task, and the date_last_modified = models.DateTimeField(auto_now=True, null=True) field has a later timestamp in the Celery task than the main thread, although I'm not sure if that's an indication of anything, i.e. it may have been updated but the update has not been flushed out to the DB.

I'm using django 1.5.1, postgresql 9.3.0, celery v3.1.0, Redis 2.6.10

Running Celery like so $ celery -A tracking worker -E -B -l info

Any ideas of why this may be happening would be greatly appreciated

Owen answered 20/12, 2013 at 5:56 Comment(0)
L
4

Are you re-getting the object after the save? I.e. not just looking at the instance you got before the save?

Liaoyang answered 24/12, 2013 at 15:5 Comment(0)
D
3

I had similar problem with Django 1.5

I guess it's because of that Django does not commit changes to database immediately.

Adding

    'OPTIONS': {
        'autocommit': True
    }

to DATABASES setting fixed the problem for me.

Problem will not exist in Django 1.6+ beacuse autocommit is the default there.

Deyo answered 20/11, 2014 at 12:59 Comment(0)
C
2

What about transactions? You can try to set CELERY_EAGER_PROPAGATES_EXCEPTIONS=True and run celery with -l DEBUG to see, is any error happens after model .save() call.

Also take care of concurrent updates. When one process reads model, then celery reads and saves same model, if initial process calls models.save() later it would override all fields in it.

Cloudberry answered 3/6, 2014 at 8:37 Comment(2)
Concurrent updates was an issue in my case, installing django-save-the-change.readthedocs.org helped. Thanks!Oni
Nowadays Django has .save(updated_fields=...) docs.djangoproject.com/en/3.0/ref/models/instances/… that can be used instead of django-save-the-change packageCloudberry
T
0

Had an issue looking like yours on Django 3.2.7. using get_nb_lines.delay(flow.pk)within an class based updateview.

After fix, I suppose it was a kind of (maybe) concurrent updates or crossing updates (dunno how to call that).

I understood that after I noticed that get_nb_lines.apply_async((flow.pk,), countdown=5)had fixed my problem. I anybody explains this another way, I'll take it.

Take care because the parameter sent into the function must be iterable as said an error alert. So in my case, I had to treat flow.pk as a list (add a comma after flow.pk)

Tanatanach answered 20/4, 2022 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.