I have a Django application for storing objects in a database and a celery task that periodically do some processing on some of these objects. The problem is that the user can delete the object after it has been selected by the celery task for processing, but before the celery task actually completed processing and saving. Therefore, when the celery task invokes .save(), the object reappears in the database, even if the user deleted it. Of course, this is really creepy for users.
So, here is the code that shows the problem:
def my_delete_view(request, pk):
thing = Thing.objects.get(pk=pk)
thing.delete()
return HttpResponseRedirect('yay')
@app.task
def my_periodic_task():
things = get_things_for_processing()
for thing in things:
process_thing(thing)
thing.save()
I was thinking of trying to fix this by adding an atomic block and a transaction to check if the object really exists before saving it:
@app.task
def my_periodic_task():
things = Thing.objects.filter(...some criteria...)
for thing in things:
process_thing(thing)
try:
with transaction.atomic():
unused = Thing.objects.select_for_update().get(pk=thing.pk)
thing.save()
except Thing.DoesNotExist:
logger.warning("Processed thing vanished")
? , , , , - .
, , . process_thing, refresh_from_db process_thing, , . , .