dbos 0.22.0a11__py3-none-any.whl → 0.23.0a1__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/_core.py CHANGED
@@ -51,6 +51,7 @@ from ._error import (
51
51
  DBOSMaxStepRetriesExceeded,
52
52
  DBOSNonExistentWorkflowError,
53
53
  DBOSRecoveryError,
54
+ DBOSWorkflowCancelledError,
54
55
  DBOSWorkflowConflictIDError,
55
56
  DBOSWorkflowFunctionNotFoundError,
56
57
  )
@@ -224,6 +225,8 @@ def _get_wf_invoke_func(
224
225
  )
225
226
  output = wf_handle.get_result()
226
227
  return output
228
+ except DBOSWorkflowCancelledError as error:
229
+ raise
227
230
  except Exception as error:
228
231
  status["status"] = "ERROR"
229
232
  status["error"] = _serialization.serialize_exception(error)
@@ -539,6 +542,13 @@ def decorate_transaction(
539
542
  raise DBOSException(
540
543
  f"Function {func.__name__} invoked before DBOS initialized"
541
544
  )
545
+
546
+ ctx = assert_current_dbos_context()
547
+ if dbosreg.is_workflow_cancelled(ctx.workflow_id):
548
+ raise DBOSWorkflowCancelledError(
549
+ f"Workflow {ctx.workflow_id} is cancelled. Aborting transaction {func.__name__}."
550
+ )
551
+
542
552
  dbos = dbosreg.dbos
543
553
  with dbos._app_db.sessionmaker() as session:
544
554
  attributes: TracedAttributes = {
@@ -560,6 +570,12 @@ def decorate_transaction(
560
570
  backoff_factor = 1.5
561
571
  max_retry_wait_seconds = 2.0
562
572
  while True:
573
+
574
+ if dbosreg.is_workflow_cancelled(ctx.workflow_id):
575
+ raise DBOSWorkflowCancelledError(
576
+ f"Workflow {ctx.workflow_id} is cancelled. Aborting transaction {func.__name__}."
577
+ )
578
+
563
579
  has_recorded_error = False
564
580
  txn_error: Optional[Exception] = None
565
581
  try:
@@ -710,6 +726,13 @@ def decorate_step(
710
726
  "operationType": OperationType.STEP.value,
711
727
  }
712
728
 
729
+ # Check if the workflow is cancelled
730
+ ctx = assert_current_dbos_context()
731
+ if dbosreg.is_workflow_cancelled(ctx.workflow_id):
732
+ raise DBOSWorkflowCancelledError(
733
+ f"Workflow {ctx.workflow_id} is cancelled. Aborting step {func.__name__}."
734
+ )
735
+
713
736
  attempts = max_attempts if retries_allowed else 1
714
737
  max_retry_interval_seconds: float = 3600 # 1 Hour
715
738
 
@@ -800,6 +823,7 @@ def decorate_step(
800
823
  ctx = get_local_dbos_context()
801
824
  if ctx and ctx.is_step():
802
825
  # Call the original function directly
826
+
803
827
  return func(*args, **kwargs)
804
828
  if ctx and ctx.is_within_workflow():
805
829
  assert ctx.is_workflow(), "Steps must be called from within workflows"
dbos/_dbos.py CHANGED
@@ -155,6 +155,7 @@ class DBOSRegistry:
155
155
  self.pollers: list[RegisteredJob] = []
156
156
  self.dbos: Optional[DBOS] = None
157
157
  self.config: Optional[ConfigFile] = None
158
+ self.workflow_cancelled_map: dict[str, bool] = {}
158
159
 
159
160
  def register_wf_function(self, name: str, wrapped_func: F, functype: str) -> None:
160
161
  if name in self.function_type_map:
@@ -197,6 +198,15 @@ class DBOSRegistry:
197
198
  else:
198
199
  self.instance_info_map[fn] = inst
199
200
 
201
+ def cancel_workflow(self, workflow_id: str) -> None:
202
+ self.workflow_cancelled_map[workflow_id] = True
203
+
204
+ def is_workflow_cancelled(self, workflow_id: str) -> bool:
205
+ return self.workflow_cancelled_map.get(workflow_id, False)
206
+
207
+ def clear_workflow_cancelled(self, workflow_id: str) -> None:
208
+ self.workflow_cancelled_map.pop(workflow_id, None)
209
+
200
210
  def compute_app_version(self) -> str:
201
211
  """
202
212
  An application's version is computed from a hash of the source of its workflows.
@@ -844,11 +854,13 @@ class DBOS:
844
854
  def cancel_workflow(cls, workflow_id: str) -> None:
845
855
  """Cancel a workflow by ID."""
846
856
  _get_dbos_instance()._sys_db.cancel_workflow(workflow_id)
857
+ _get_or_create_dbos_registry().cancel_workflow(workflow_id)
847
858
 
848
859
  @classmethod
849
860
  def resume_workflow(cls, workflow_id: str) -> WorkflowHandle[Any]:
850
861
  """Resume a workflow by ID."""
851
862
  _get_dbos_instance()._sys_db.resume_workflow(workflow_id)
863
+ _get_or_create_dbos_registry().clear_workflow_cancelled(workflow_id)
852
864
  return execute_workflow_by_id(_get_dbos_instance(), workflow_id, False)
853
865
 
854
866
  @classproperty
dbos/_error.py CHANGED
@@ -36,6 +36,7 @@ class DBOSErrorCode(Enum):
36
36
  MaxStepRetriesExceeded = 7
37
37
  NotAuthorized = 8
38
38
  ConflictingWorkflowError = 9
39
+ WorkflowCancelled = 10
39
40
  ConflictingRegistrationError = 25
40
41
 
41
42
 
@@ -130,6 +131,16 @@ class DBOSMaxStepRetriesExceeded(DBOSException):
130
131
  )
131
132
 
132
133
 
134
+ class DBOSWorkflowCancelledError(DBOSException):
135
+ """Exception raised when the workflow has already been cancelled."""
136
+
137
+ def __init__(self, msg: str) -> None:
138
+ super().__init__(
139
+ msg,
140
+ dbos_error_code=DBOSErrorCode.WorkflowCancelled.value,
141
+ )
142
+
143
+
133
144
  class DBOSConflictingRegistrationError(DBOSException):
134
145
  """Exception raised when conflicting decorators are applied to the same function."""
135
146
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 0.22.0a11
3
+ Version: 0.23.0a1
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-0.22.0a11.dist-info/METADATA,sha256=GwtVyx4eSaBm_pisSa54YLA2Fu8vtttyOkeuahFU9SE,5310
2
- dbos-0.22.0a11.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- dbos-0.22.0a11.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
- dbos-0.22.0a11.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
1
+ dbos-0.23.0a1.dist-info/METADATA,sha256=NXo3Kx4nz7Ri3w7fDiqiycU1XJn9QPLuttIHdEwr6Lk,5309
2
+ dbos-0.23.0a1.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ dbos-0.23.0a1.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
+ dbos-0.23.0a1.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
5
5
  dbos/__init__.py,sha256=CxRHBHEthPL4PZoLbZhp3rdm44-KkRTT2-7DkK9d4QQ,724
6
6
  dbos/_admin_server.py,sha256=YiVn5lywz2Vg8_juyNHOYl0HVEy48--7b4phwK7r92o,5732
7
7
  dbos/_app_db.py,sha256=_tv2vmPjjiaikwgxH3mqxgJ4nUUcG2-0uMXKWCqVu1c,5509
@@ -10,12 +10,12 @@ dbos/_cloudutils/authentication.py,sha256=V0fCWQN9stCkhbuuxgPTGpvuQcDqfU3KAxPAh0
10
10
  dbos/_cloudutils/cloudutils.py,sha256=YC7jGsIopT0KveLsqbRpQk2KlRBk-nIRC_UCgep4f3o,7797
11
11
  dbos/_cloudutils/databases.py,sha256=_shqaqSvhY4n2ScgQ8IP5PDZvzvcx3YBKV8fj-cxhSY,8543
12
12
  dbos/_context.py,sha256=gikN5lUVqnvR-ISoOElXYeYsR_BO2whebB3YP2DJBM4,17713
13
- dbos/_core.py,sha256=b1IL3LDRGmomHhcs929n_G2pfFSmNuSxFrwhcBuo20k,35519
13
+ dbos/_core.py,sha256=i6ehRlYuVQ9cBubCuu060ArwrTF7XjrOnHpGMT6D4l0,36512
14
14
  dbos/_croniter.py,sha256=hbhgfsHBqclUS8VeLnJ9PSE9Z54z6mi4nnrr1aUXn0k,47561
15
15
  dbos/_db_wizard.py,sha256=6tfJaCRa1NtkUdNW75a2yvi_mEgnPJ9C1HP2zPG1hCU,8067
16
- dbos/_dbos.py,sha256=h25S5Mjl1JAfwMEpqRdyBSuUB_HI3TC8J9Nqtqy_XwQ,38453
16
+ dbos/_dbos.py,sha256=g6W-WqGNTMuLmX0axmH7qJKdIR252J7a7_4bUukRX4Q,39027
17
17
  dbos/_dbos_config.py,sha256=DfiqVVxNqnafkocSzLqBp1Ig5vCviDTDK_GO3zTtQqI,8298
18
- dbos/_error.py,sha256=NqlobQneZ2ycCQacXc8a38TIOHxFRjBXdF40i3wZUaA,4775
18
+ dbos/_error.py,sha256=xqB7b7g5AF_OwOvqLKLXL1xldn2gAtORix2ZC2B8zK0,5089
19
19
  dbos/_fastapi.py,sha256=ke03vqsSYDnO6XeOtOVFXj0-f-v1MGsOxa9McaROvNc,3616
20
20
  dbos/_flask.py,sha256=DZKUZR5-xOzPI7tYZ53r2PvvHVoAb8SYwLzMVFsVfjI,2608
21
21
  dbos/_kafka.py,sha256=o6DbwnsYRDtvVTZVsN7BAK8cdP79AfoWX3Q7CGY2Yuo,4199
@@ -60,4 +60,4 @@ dbos/cli/cli.py,sha256=_tXw2IQrWW7fV_h51f_R99vEBSi6aMLz-vCOxKaENiQ,14155
60
60
  dbos/dbos-config.schema.json,sha256=X5TpXNcARGceX0zQs0fVgtZW_Xj9uBbY5afPt9Rz9yk,5741
61
61
  dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
62
62
  version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
63
- dbos-0.22.0a11.dist-info/RECORD,,
63
+ dbos-0.23.0a1.dist-info/RECORD,,