dbos 1.1.0a2__py3-none-any.whl → 1.1.0a3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dbos might be problematic. Click here for more details.
- dbos/_sys_db.py +65 -14
- {dbos-1.1.0a2.dist-info → dbos-1.1.0a3.dist-info}/METADATA +1 -1
- {dbos-1.1.0a2.dist-info → dbos-1.1.0a3.dist-info}/RECORD +6 -6
- {dbos-1.1.0a2.dist-info → dbos-1.1.0a3.dist-info}/WHEEL +0 -0
- {dbos-1.1.0a2.dist-info → dbos-1.1.0a3.dist-info}/entry_points.txt +0 -0
- {dbos-1.1.0a2.dist-info → dbos-1.1.0a3.dist-info}/licenses/LICENSE +0 -0
dbos/_sys_db.py
CHANGED
@@ -222,6 +222,47 @@ class StepInfo(TypedDict):
|
|
222
222
|
_dbos_null_topic = "__null__topic__"
|
223
223
|
|
224
224
|
|
225
|
+
class ConditionCount(TypedDict):
|
226
|
+
condition: threading.Condition
|
227
|
+
count: int
|
228
|
+
|
229
|
+
|
230
|
+
class ThreadSafeConditionDict:
|
231
|
+
def __init__(self) -> None:
|
232
|
+
self._dict: Dict[str, ConditionCount] = {}
|
233
|
+
self._lock = threading.Lock()
|
234
|
+
|
235
|
+
def get(self, key: str) -> Optional[threading.Condition]:
|
236
|
+
with self._lock:
|
237
|
+
if key not in self._dict:
|
238
|
+
# Key does not exist, return None
|
239
|
+
return None
|
240
|
+
return self._dict[key]["condition"]
|
241
|
+
|
242
|
+
def set(
|
243
|
+
self, key: str, value: threading.Condition
|
244
|
+
) -> tuple[bool, threading.Condition]:
|
245
|
+
with self._lock:
|
246
|
+
if key in self._dict:
|
247
|
+
# Key already exists, do not overwrite. Increment the wait count.
|
248
|
+
cc = self._dict[key]
|
249
|
+
cc["count"] += 1
|
250
|
+
return False, cc["condition"]
|
251
|
+
self._dict[key] = ConditionCount(condition=value, count=1)
|
252
|
+
return True, value
|
253
|
+
|
254
|
+
def pop(self, key: str) -> None:
|
255
|
+
with self._lock:
|
256
|
+
if key in self._dict:
|
257
|
+
cc = self._dict[key]
|
258
|
+
cc["count"] -= 1
|
259
|
+
if cc["count"] == 0:
|
260
|
+
# No more threads waiting on this condition, remove it
|
261
|
+
del self._dict[key]
|
262
|
+
else:
|
263
|
+
dbos_logger.warning(f"Key {key} not found in condition dictionary.")
|
264
|
+
|
265
|
+
|
225
266
|
class SystemDatabase:
|
226
267
|
|
227
268
|
def __init__(
|
@@ -248,8 +289,8 @@ class SystemDatabase:
|
|
248
289
|
self._engine_kwargs = engine_kwargs
|
249
290
|
|
250
291
|
self.notification_conn: Optional[psycopg.connection.Connection] = None
|
251
|
-
self.notifications_map
|
252
|
-
self.workflow_events_map
|
292
|
+
self.notifications_map = ThreadSafeConditionDict()
|
293
|
+
self.workflow_events_map = ThreadSafeConditionDict()
|
253
294
|
|
254
295
|
# Now we can run background processes
|
255
296
|
self._run_background_processes = True
|
@@ -1288,7 +1329,12 @@ class SystemDatabase:
|
|
1288
1329
|
condition = threading.Condition()
|
1289
1330
|
# Must acquire first before adding to the map. Otherwise, the notification listener may notify it before the condition is acquired and waited.
|
1290
1331
|
condition.acquire()
|
1291
|
-
self.notifications_map
|
1332
|
+
success, _ = self.notifications_map.set(payload, condition)
|
1333
|
+
if not success:
|
1334
|
+
# This should not happen, but if it does, it means the workflow is executed concurrently.
|
1335
|
+
condition.release()
|
1336
|
+
self.notifications_map.pop(payload)
|
1337
|
+
raise DBOSWorkflowConflictIDError(workflow_uuid)
|
1292
1338
|
|
1293
1339
|
# Check if the key is already in the database. If not, wait for the notification.
|
1294
1340
|
init_recv: Sequence[Any]
|
@@ -1381,11 +1427,11 @@ class SystemDatabase:
|
|
1381
1427
|
f"Received notification on channel: {channel}, payload: {notify.payload}"
|
1382
1428
|
)
|
1383
1429
|
if channel == "dbos_notifications_channel":
|
1384
|
-
if
|
1385
|
-
notify.payload
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1430
|
+
if notify.payload:
|
1431
|
+
condition = self.notifications_map.get(notify.payload)
|
1432
|
+
if condition is None:
|
1433
|
+
# No condition found for this payload
|
1434
|
+
continue
|
1389
1435
|
condition.acquire()
|
1390
1436
|
condition.notify_all()
|
1391
1437
|
condition.release()
|
@@ -1393,11 +1439,11 @@ class SystemDatabase:
|
|
1393
1439
|
f"Signaled notifications condition for {notify.payload}"
|
1394
1440
|
)
|
1395
1441
|
elif channel == "dbos_workflow_events_channel":
|
1396
|
-
if
|
1397
|
-
notify.payload
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1442
|
+
if notify.payload:
|
1443
|
+
condition = self.workflow_events_map.get(notify.payload)
|
1444
|
+
if condition is None:
|
1445
|
+
# No condition found for this payload
|
1446
|
+
continue
|
1401
1447
|
condition.acquire()
|
1402
1448
|
condition.notify_all()
|
1403
1449
|
condition.release()
|
@@ -1535,8 +1581,13 @@ class SystemDatabase:
|
|
1535
1581
|
|
1536
1582
|
payload = f"{target_uuid}::{key}"
|
1537
1583
|
condition = threading.Condition()
|
1538
|
-
self.workflow_events_map[payload] = condition
|
1539
1584
|
condition.acquire()
|
1585
|
+
success, existing_condition = self.workflow_events_map.set(payload, condition)
|
1586
|
+
if not success:
|
1587
|
+
# Wait on the existing condition
|
1588
|
+
condition.release()
|
1589
|
+
condition = existing_condition
|
1590
|
+
condition.acquire()
|
1540
1591
|
|
1541
1592
|
# Check if the key is already in the database. If not, wait for the notification.
|
1542
1593
|
init_recv: Sequence[Any]
|
@@ -1,7 +1,7 @@
|
|
1
|
-
dbos-1.1.
|
2
|
-
dbos-1.1.
|
3
|
-
dbos-1.1.
|
4
|
-
dbos-1.1.
|
1
|
+
dbos-1.1.0a3.dist-info/METADATA,sha256=wwmIbv3PGphti-I6d0es4O3hZMHu7m7hXZbMfrko2WM,13267
|
2
|
+
dbos-1.1.0a3.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
|
3
|
+
dbos-1.1.0a3.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
|
4
|
+
dbos-1.1.0a3.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
|
5
5
|
dbos/__init__.py,sha256=NssPCubaBxdiKarOWa-wViz1hdJSkmBGcpLX_gQ4NeA,891
|
6
6
|
dbos/__main__.py,sha256=G7Exn-MhGrVJVDbgNlpzhfh8WMX_72t3_oJaFT9Lmt8,653
|
7
7
|
dbos/_admin_server.py,sha256=A_28_nJ1nBBYDmCxtklJR9O2v14JRMtD1rAo_D4y8Kc,9764
|
@@ -47,7 +47,7 @@ dbos/_schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
47
|
dbos/_schemas/application_database.py,sha256=SypAS9l9EsaBHFn9FR8jmnqt01M74d9AF1AMa4m2hhI,1040
|
48
48
|
dbos/_schemas/system_database.py,sha256=3Z0L72bOgHnusK1hBaETWU9RfiLBP0QnS-fdu41i0yY,5835
|
49
49
|
dbos/_serialization.py,sha256=bWuwhXSQcGmiazvhJHA5gwhrRWxtmFmcCFQSDJnqqkU,3666
|
50
|
-
dbos/_sys_db.py,sha256=
|
50
|
+
dbos/_sys_db.py,sha256=cgUpkgVF8jz_dcseShiJl4jFqoPlF24UadjVZ7LQ2qc,83235
|
51
51
|
dbos/_templates/dbos-db-starter/README.md,sha256=GhxhBj42wjTt1fWEtwNriHbJuKb66Vzu89G4pxNHw2g,930
|
52
52
|
dbos/_templates/dbos-db-starter/__package/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
53
|
dbos/_templates/dbos-db-starter/__package/main.py.dbos,sha256=aQnBPSSQpkB8ERfhf7gB7P9tsU6OPKhZscfeh0yiaD8,2702
|
@@ -67,4 +67,4 @@ dbos/cli/cli.py,sha256=HinoCGrAUTiSeq7AAoCFfhdiE0uDw7vLMuDMN1_YTLI,20705
|
|
67
67
|
dbos/dbos-config.schema.json,sha256=CjaspeYmOkx6Ip_pcxtmfXJTn_YGdSx_0pcPBF7KZmo,6060
|
68
68
|
dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
|
69
69
|
version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
|
70
|
-
dbos-1.1.
|
70
|
+
dbos-1.1.0a3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|