Browse Source

test(extras): Release the data lock explicitly

Closing the helper's connection does not wait for PostgreSQL to release
its session advisory lock, so the deletion which follows could still see
the lock held and abort. Release it with pg_advisory_unlock() instead.

Fixes #23145
Martin Hauser 1 ngày trước cách đây
mục cha
commit
7d124a2b1b
1 tập tin đã thay đổi với 12 bổ sung3 xóa
  1. 12 3
      netbox/extras/tests/test_customfields.py

+ 12 - 3
netbox/extras/tests/test_customfields.py

@@ -2876,9 +2876,18 @@ def hold_data_lock(custom_field):
             cursor.execute('SELECT pg_try_advisory_lock(%s, %s)', lock_key)
             if not cursor.fetchone()[0]:
                 raise RuntimeError(f"Failed to acquire the data lock for {custom_field}")
-        yield
+        released = False
+        try:
+            yield
+        finally:
+            # Closing the connection releases the lock asynchronously, so the next deletion can race it
+            with connection.cursor() as cursor:
+                cursor.execute('SELECT pg_advisory_unlock(%s, %s)', lock_key)
+                released = cursor.fetchone()[0]
+        # Outside the finally, so a failing body is reported as itself
+        if not released:
+            raise RuntimeError(f"Failed to release the data lock for {custom_field}")
     finally:
-        # Closing the session releases any advisory lock held on it
         connection.close()
 
 
@@ -3739,7 +3748,7 @@ class DeferredCustomFieldDataTestCase(TestCase):
 
         # delete() has returned and its own atomic block has exited, but the enclosing transaction
         # has yet to commit, so the lock must still be held
-        with self.assertRaises(RuntimeError):
+        with self.assertRaisesMessage(RuntimeError, "Failed to acquire the data lock"):
             with hold_data_lock(cf):
                 pass