Skip to content

Commit abca7f3

Browse files
authored
fix: release the id increment lock after generation (#87)
- the success path of DataAdapter._id leaked the RLock acquisition, deadlocking inserts from background threads (scheduler jobs) on non Mongo adapters - regression test asserts the lock is acquirable from another thread
1 parent cdcfcad commit abca7f3

3 files changed

Lines changed: 21 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
### Fixed
1919

20-
*
20+
* Identifier generation (`DataAdapter._id`) no longer leaks the increment lock, which deadlocked inserts from background threads (e.g. scheduler jobs over the tiny adapter) - [#86](https://github.com/hivesolutions/appier/issues/86)
2121

2222
## [1.46.0] - 2026-05-31
2323

src/appier/data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def _id(self):
105105
try:
106106
token += struct.pack(">i", self._inc)[1:4]
107107
self._inc = (self._inc + 1) % 0xFFFFFF
108-
except Exception:
108+
finally:
109109
self._inc_lock.release()
110110
token_s = binascii.hexlify(token)
111111
token_s = legacy.str(token_s)

src/appier/test/data.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
import os
3232
import tempfile
33+
import threading
3334
import unittest
3435

3536
import appier
@@ -43,6 +44,24 @@ def test_id(self):
4344
self.assertEqual(type(identifier), str)
4445
self.assertEqual(len(identifier), 24)
4546

47+
def test_id_lock_release(self):
48+
adapter = appier.DataAdapter()
49+
adapter._id()
50+
51+
result = []
52+
53+
def acquire():
54+
acquired = adapter._inc_lock.acquire(False)
55+
if acquired:
56+
adapter._inc_lock.release()
57+
result.append(acquired)
58+
59+
thread = threading.Thread(target=acquire)
60+
thread.start()
61+
thread.join()
62+
63+
self.assertEqual(result, [True])
64+
4665
def test_drop_db_missing(self):
4766
fd, file_path = tempfile.mkstemp()
4867
os.close(fd)

0 commit comments

Comments
 (0)