Improve detection of missing transactions

This commit is contained in:
Raphael Michel
2021-10-26 18:06:49 +02:00
parent 2dceff1218
commit bb353e5fde

View File

@@ -58,14 +58,16 @@ def _fail(message):
def _check_for_dirty_orders(): def _check_for_dirty_orders():
if getattr(dirty_transactions, 'order_ids', None) is None: if getattr(dirty_transactions, 'order_ids', None) is None:
dirty_transactions.order_ids = set() dirty_transactions.order_ids = set()
if dirty_transactions.order_ids and dirty_transactions.order_ids != {None}: try:
_fail( if dirty_transactions.order_ids and dirty_transactions.order_ids != {None}:
f"In the transaction that just ended, you created or modified an Order, OrderPosition, or OrderFee " _fail(
f"object in a way that you should have called `order.create_transactions()` afterwards. The transaction " f"In the transaction that just ended, you created or modified an Order, OrderPosition, or OrderFee "
f"still went through and your data can be fixed with the `create_order_transactions` management command " f"object in a way that you should have called `order.create_transactions()` afterwards. The transaction "
f"but you should update your code to prevent this from happening. Affected order IDs: {dirty_transactions.order_ids}" f"still went through and your data can be fixed with the `create_order_transactions` management command "
) f"but you should update your code to prevent this from happening. Affected order IDs: {dirty_transactions.order_ids}"
dirty_transactions.order_ids.clear() )
finally:
dirty_transactions.order_ids.clear()
def _transactions_mark_order_dirty(order_id, using=None): def _transactions_mark_order_dirty(order_id, using=None):
@@ -81,9 +83,9 @@ def _transactions_mark_order_dirty(order_id, using=None):
# This went through non-test code, let's consider it non-test # This went through non-test code, let's consider it non-test
break break
if getattr(dirty_transactions, 'order_ids', None) is None: if order_id is None:
dirty_transactions.order_ids = set() return
dirty_transactions.order_ids.add(order_id)
conn = transaction.get_connection(using) conn = transaction.get_connection(using)
if not conn.in_atomic_block: if not conn.in_atomic_block:
_fail( _fail(
@@ -92,8 +94,14 @@ def _transactions_mark_order_dirty(order_id, using=None):
"doing it inside a database transaction!" "doing it inside a database transaction!"
) )
if getattr(dirty_transactions, 'order_ids', None) is None:
dirty_transactions.order_ids = set()
if _check_for_dirty_orders not in [func for savepoint_id, func in conn.run_on_commit]: if _check_for_dirty_orders not in [func for savepoint_id, func in conn.run_on_commit]:
transaction.on_commit(_check_for_dirty_orders, using) transaction.on_commit(_check_for_dirty_orders, using)
dirty_transactions.order_ids.clear() # This is necessary to clean up after old threads with rollbacked transactions
dirty_transactions.order_ids.add(order_id)
def _transactions_mark_order_clean(order_id): def _transactions_mark_order_clean(order_id):