Two problems.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # ====================================================================== # Q: Find the bug. # # Two problems. 1) The Celery task may run before the commit, fail to find the # order, or send an email for an order that was eventually rolled back. Fix: # transaction.on_commit(lambda: send_confirmation_email.delay(order.id)). 2) # Charging the card inside a transaction keeps the transaction open while we # wait for an external system, and if it rolls back after the charge, the # customer was charged without an order. Correct approach: commit a pending # order, charge outside the transaction with an idempotency key, then update the # status. # ====================================================================== @transaction.atomic def place_order(customer, items): order = Order.objects.create(customer=customer, status='pending') ... send_confirmation_email.delay(order.id) charge_card(order) # may raise an exception |