dbos 1.14.0a6__py3-none-any.whl → 1.14.0a9__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.
dbos/_debouncer.py CHANGED
@@ -147,7 +147,6 @@ class Debouncer(Generic[P, R]):
147
147
  self,
148
148
  workflow_name: str,
149
149
  *,
150
- debounce_key: str,
151
150
  debounce_timeout_sec: Optional[float] = None,
152
151
  queue: Optional[Queue] = None,
153
152
  ):
@@ -157,13 +156,11 @@ class Debouncer(Generic[P, R]):
157
156
  "queue_name": queue.name if queue else None,
158
157
  "workflow_name": workflow_name,
159
158
  }
160
- self.debounce_key = debounce_key
161
159
 
162
160
  @staticmethod
163
161
  def create(
164
162
  workflow: Callable[P, R],
165
163
  *,
166
- debounce_key: str,
167
164
  debounce_timeout_sec: Optional[float] = None,
168
165
  queue: Optional[Queue] = None,
169
166
  ) -> "Debouncer[P, R]":
@@ -172,7 +169,6 @@ class Debouncer(Generic[P, R]):
172
169
  raise TypeError("Only workflow functions may be debounced, not methods")
173
170
  return Debouncer[P, R](
174
171
  get_dbos_func_name(workflow),
175
- debounce_key=debounce_key,
176
172
  debounce_timeout_sec=debounce_timeout_sec,
177
173
  queue=queue,
178
174
  )
@@ -181,7 +177,6 @@ class Debouncer(Generic[P, R]):
181
177
  def create_async(
182
178
  workflow: Callable[P, Coroutine[Any, Any, R]],
183
179
  *,
184
- debounce_key: str,
185
180
  debounce_timeout_sec: Optional[float] = None,
186
181
  queue: Optional[Queue] = None,
187
182
  ) -> "Debouncer[P, R]":
@@ -190,13 +185,16 @@ class Debouncer(Generic[P, R]):
190
185
  raise TypeError("Only workflow functions may be debounced, not methods")
191
186
  return Debouncer[P, R](
192
187
  get_dbos_func_name(workflow),
193
- debounce_key=debounce_key,
194
188
  debounce_timeout_sec=debounce_timeout_sec,
195
189
  queue=queue,
196
190
  )
197
191
 
198
192
  def debounce(
199
- self, debounce_period_sec: float, *args: P.args, **kwargs: P.kwargs
193
+ self,
194
+ debounce_key: str,
195
+ debounce_period_sec: float,
196
+ *args: P.args,
197
+ **kwargs: P.kwargs,
200
198
  ) -> "WorkflowHandle[R]":
201
199
  from dbos._dbos import DBOS, _get_dbos_instance
202
200
 
@@ -232,7 +230,8 @@ class Debouncer(Generic[P, R]):
232
230
  while True:
233
231
  try:
234
232
  # Attempt to enqueue a debouncer for this workflow.
235
- with SetEnqueueOptions(deduplication_id=self.debounce_key):
233
+ deduplication_id = f"{self.options['workflow_name']}-{debounce_key}"
234
+ with SetEnqueueOptions(deduplication_id=deduplication_id):
236
235
  with SetWorkflowTimeout(None):
237
236
  internal_queue.enqueue(
238
237
  debouncer_workflow,
@@ -249,7 +248,7 @@ class Debouncer(Generic[P, R]):
249
248
  def get_deduplicated_workflow() -> Optional[str]:
250
249
  return dbos._sys_db.get_deduplicated_workflow(
251
250
  queue_name=internal_queue.name,
252
- deduplication_id=self.debounce_key,
251
+ deduplication_id=deduplication_id,
253
252
  )
254
253
 
255
254
  dedup_wfid = dbos._sys_db.call_function_as_step(
@@ -281,6 +280,7 @@ class Debouncer(Generic[P, R]):
281
280
 
282
281
  async def debounce_async(
283
282
  self,
283
+ debounce_key: str,
284
284
  debounce_period_sec: float,
285
285
  *args: P.args,
286
286
  **kwargs: P.kwargs,
@@ -289,7 +289,7 @@ class Debouncer(Generic[P, R]):
289
289
 
290
290
  dbos = _get_dbos_instance()
291
291
  handle = await asyncio.to_thread(
292
- self.debounce, debounce_period_sec, *args, **kwargs
292
+ self.debounce, debounce_key, debounce_period_sec, *args, **kwargs
293
293
  )
294
294
  return WorkflowHandleAsyncPolling(handle.workflow_id, dbos)
295
295
 
@@ -301,7 +301,6 @@ class DebouncerClient:
301
301
  client: DBOSClient,
302
302
  workflow_options: EnqueueOptions,
303
303
  *,
304
- debounce_key: str,
305
304
  debounce_timeout_sec: Optional[float] = None,
306
305
  queue: Optional[Queue] = None,
307
306
  ):
@@ -311,11 +310,10 @@ class DebouncerClient:
311
310
  "queue_name": queue.name if queue else None,
312
311
  "workflow_name": workflow_options["workflow_name"],
313
312
  }
314
- self.debounce_key = debounce_key
315
313
  self.client = client
316
314
 
317
315
  def debounce(
318
- self, debounce_period_sec: float, *args: Any, **kwargs: Any
316
+ self, debounce_key: str, debounce_period_sec: float, *args: Any, **kwargs: Any
319
317
  ) -> "WorkflowHandle[R]":
320
318
 
321
319
  ctxOptions: ContextOptions = {
@@ -333,10 +331,13 @@ class DebouncerClient:
333
331
  while True:
334
332
  try:
335
333
  # Attempt to enqueue a debouncer for this workflow.
334
+ deduplication_id = (
335
+ f"{self.debouncer_options['workflow_name']}-{debounce_key}"
336
+ )
336
337
  debouncer_options: EnqueueOptions = {
337
338
  "workflow_name": DEBOUNCER_WORKFLOW_NAME,
338
339
  "queue_name": INTERNAL_QUEUE_NAME,
339
- "deduplication_id": self.debounce_key,
340
+ "deduplication_id": deduplication_id,
340
341
  }
341
342
  self.client.enqueue(
342
343
  debouncer_options,
@@ -353,7 +354,7 @@ class DebouncerClient:
353
354
  # If there is already a debouncer, send a message to it.
354
355
  dedup_wfid = self.client._sys_db.get_deduplicated_workflow(
355
356
  queue_name=INTERNAL_QUEUE_NAME,
356
- deduplication_id=self.debounce_key,
357
+ deduplication_id=deduplication_id,
357
358
  )
358
359
  if dedup_wfid is None:
359
360
  continue
@@ -384,10 +385,10 @@ class DebouncerClient:
384
385
  )
385
386
 
386
387
  async def debounce_async(
387
- self, debounce_period_sec: float, *args: Any, **kwargs: Any
388
+ self, deboucne_key: str, debounce_period_sec: float, *args: Any, **kwargs: Any
388
389
  ) -> "WorkflowHandleAsync[R]":
389
390
  handle: "WorkflowHandle[R]" = await asyncio.to_thread(
390
- self.debounce, debounce_period_sec, *args, **kwargs
391
+ self.debounce, deboucne_key, debounce_period_sec, *args, **kwargs
391
392
  )
392
393
  return WorkflowHandleClientAsyncPolling[R](
393
394
  handle.workflow_id, self.client._sys_db
dbos/_sys_db.py CHANGED
@@ -1934,8 +1934,13 @@ class SystemDatabase(ABC):
1934
1934
  )
1935
1935
  if self._debug_mode and recorded_output is None:
1936
1936
  raise Exception(
1937
- "called set_event in debug mode without a previous execution"
1937
+ "called writeStream in debug mode without a previous execution"
1938
1938
  )
1939
+ if recorded_output is not None:
1940
+ dbos_logger.debug(
1941
+ f"Replaying writeStream, id: {function_id}, key: {key}"
1942
+ )
1943
+ return
1939
1944
  # Find the maximum offset for this workflow_uuid and key combination
1940
1945
  max_offset_result = c.execute(
1941
1946
  sa.select(sa.func.max(SystemSchema.streams.c.offset)).where(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 1.14.0a6
3
+ Version: 1.14.0a9
4
4
  Summary: Ultra-lightweight durable execution in Python
5
5
  Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
6
  License: MIT
@@ -1,7 +1,7 @@
1
- dbos-1.14.0a6.dist-info/METADATA,sha256=SkLS0HlCdwrO5LyiXP_ls-yAZNRlnUJkFWSUbS4qiqM,13268
2
- dbos-1.14.0a6.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- dbos-1.14.0a6.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
- dbos-1.14.0a6.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
1
+ dbos-1.14.0a9.dist-info/METADATA,sha256=z_qeuQRuFMPDSGviV29KhLtBuULZu7f-tBlL2j8rLVU,13268
2
+ dbos-1.14.0a9.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
+ dbos-1.14.0a9.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
+ dbos-1.14.0a9.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
5
5
  dbos/__init__.py,sha256=pT4BuNLDCrIQX27vQG8NlfxX6PZRU7r9miq4thJTszU,982
6
6
  dbos/__main__.py,sha256=G7Exn-MhGrVJVDbgNlpzhfh8WMX_72t3_oJaFT9Lmt8,653
7
7
  dbos/_admin_server.py,sha256=e8ELhcDWqR3_PNobnNgUvLGh5lzZq0yFSF6dvtzoQRI,16267
@@ -32,7 +32,7 @@ dbos/_core.py,sha256=plF80l5Rh_bBpy5PFZy3p3ux6agmYkUgZq8e36i68F4,50443
32
32
  dbos/_croniter.py,sha256=XHAyUyibs_59sJQfSNWkP7rqQY6_XrlfuuCxk4jYqek,47559
33
33
  dbos/_dbos.py,sha256=AgkcE9YSC9KWsDUNfEhdbkfR9NjT0seZDAOunb3n61w,58201
34
34
  dbos/_dbos_config.py,sha256=_26ktif8qAZW4Ujg6dZfLkYO7dE4CI8b3IQbw_5YkpA,25710
35
- dbos/_debouncer.py,sha256=zsfGoFCNs2DnCTSkv6pDgNspzOnqsoquSlHgmi2nbXo,15124
35
+ dbos/_debouncer.py,sha256=KMu64pbq7mUAY4g_9_gzP4a4FKDOv5BbLhkkh9PcBuA,15217
36
36
  dbos/_debug.py,sha256=99j2SChWmCPAlZoDmjsJGe77tpU2LEa8E2TtLAnnh7o,1831
37
37
  dbos/_docker_pg_helper.py,sha256=tLJXWqZ4S-ExcaPnxg_i6cVxL6ZxrYlZjaGsklY-s2I,6115
38
38
  dbos/_error.py,sha256=GwO0Ng4d4iB52brY09-Ss6Cz_V28Xc0D0cRCzZ6XmNM,8688
@@ -53,7 +53,7 @@ dbos/_schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  dbos/_schemas/application_database.py,sha256=SypAS9l9EsaBHFn9FR8jmnqt01M74d9AF1AMa4m2hhI,1040
54
54
  dbos/_schemas/system_database.py,sha256=-dAKk-_Y3vzbpLT4ei-sIrBQgFyQiwPj1enZb1TYc8I,4943
55
55
  dbos/_serialization.py,sha256=VOMpwuJ6IskOUEegFDPqjIoV5PoBWfH9BgtnuI1jLok,3906
56
- dbos/_sys_db.py,sha256=fvrO3F-tOh8zgfxTNbnwksWLVdXYZVQJceIp6ZJOOlw,82838
56
+ dbos/_sys_db.py,sha256=SspVk-wYmE6xZLuyYQUclwh_AMjnkDXcog5g5WmYn7c,83036
57
57
  dbos/_sys_db_postgres.py,sha256=WcG-f1CUzUNBGEOjqKEp6DDraN63jTnJ6CAfieCcxOs,7555
58
58
  dbos/_sys_db_sqlite.py,sha256=xT9l-czMhLmfuu5UcnBzAyUxSFgzt3XtEWx9t_D8mZs,7361
59
59
  dbos/_templates/dbos-db-starter/README.md,sha256=GhxhBj42wjTt1fWEtwNriHbJuKb66Vzu89G4pxNHw2g,930
@@ -76,4 +76,4 @@ dbos/cli/migration.py,sha256=5GiyagLZkyVvDz3StYxtFdkFoKFCmh6eSXjzsIGhZ_A,3330
76
76
  dbos/dbos-config.schema.json,sha256=LyUT1DOTaAwOP6suxQGS5KemVIqXGPyu_q7Hbo0neA8,6192
77
77
  dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
78
78
  version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
79
- dbos-1.14.0a6.dist-info/RECORD,,
79
+ dbos-1.14.0a9.dist-info/RECORD,,