What's the correct way to use transaction.on_commit with Celery tasks in Django?
Approach 1: Without transaction.atomic
Source: https://adamj.eu/tech/2022/08/22/use-partial-with-djangos-transaction-on-commit/
def order_created(order):
order.status = 'created'
order.save()
transaction.on_commit(
partial(send_order_email.delay, order_id=order.id)
)
Approach 2: With transaction.atomic
def order_created(order):
with transaction.atomic():
order.status = 'created'
order.save()
transaction.on_commit(
partial(send_order_email.delay, order_id=order.id)
)
Which approach is correct and why? The save() operation makes database changes, but examples differ on whether transaction.atomic is needed. (ATOMIC_REQUESTS=False in settings)
In the first example transaction.on_commit
will result in error if there is no transaction open (related docs), plus save()
will be executed right away so there is no need for on_commit
at all.
In second example, Celery task will be queued at the end of successful transaction. As I understand your question, this is expected behaviour