I have a django view which sends a payment receipt, and in multi-threaded environments, this view sends the receipt multiple times if called more than once in quick succession. My code which does the update looks like
updated = Transaction.objects \
.filter(id=transaction_id, status='processing') \
.update(status='paid')
if updated:
# send email
Everything I've read on the internet suggests that selecting and updating rows that need to be updated in one query as I've done here should work. What am I doing wrong?
I also tried
with transaction.atomic():
trans = Transaction.objects.select_for_update() \
.get(id=transaction_id)
if trans.status == 'processing':
trans.status = 'paid'
trans.save()
updated = True
else:
updated = False
Other things I've tried:
The site runs apache/mod_wsgi, Django 1.8 and Postgres 9.4, and the problem goes away if I set threads=1 processes=1 in my mod_wsgi configuration. I also reproduced the problem with gunicorn, with multiple workers. It's hosted on Webfaction although would assume that doesn't matter.