dbos 1.11.0a6__tar.gz → 1.12.0a1__tar.gz

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.

Files changed (113) hide show
  1. {dbos-1.11.0a6 → dbos-1.12.0a1}/PKG-INFO +1 -1
  2. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_context.py +31 -0
  3. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_core.py +5 -7
  4. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_dbos.py +4 -0
  5. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_error.py +1 -1
  6. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_recovery.py +17 -12
  7. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_registrations.py +1 -1
  8. {dbos-1.11.0a6 → dbos-1.12.0a1}/pyproject.toml +1 -1
  9. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_failures.py +23 -0
  10. {dbos-1.11.0a6 → dbos-1.12.0a1}/LICENSE +0 -0
  11. {dbos-1.11.0a6 → dbos-1.12.0a1}/README.md +0 -0
  12. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/__init__.py +0 -0
  13. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/__main__.py +0 -0
  14. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_admin_server.py +0 -0
  15. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_app_db.py +0 -0
  16. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_classproperty.py +0 -0
  17. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_client.py +0 -0
  18. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_conductor/conductor.py +0 -0
  19. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_conductor/protocol.py +0 -0
  20. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_croniter.py +0 -0
  21. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_dbos_config.py +0 -0
  22. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_debug.py +0 -0
  23. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_docker_pg_helper.py +0 -0
  24. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_event_loop.py +0 -0
  25. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_fastapi.py +0 -0
  26. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_flask.py +0 -0
  27. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_kafka.py +0 -0
  28. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_kafka_message.py +0 -0
  29. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_logger.py +0 -0
  30. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/env.py +0 -0
  31. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/script.py.mako +0 -0
  32. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/01ce9f07bd10_streaming.py +0 -0
  33. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/04ca4f231047_workflow_queues_executor_id.py +0 -0
  34. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/27ac6900c6ad_add_queue_dedup.py +0 -0
  35. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/50f3227f0b4b_fix_job_queue.py +0 -0
  36. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/5c361fc04708_added_system_tables.py +0 -0
  37. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/66478e1b95e5_consolidate_queues.py +0 -0
  38. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/83f3732ae8e7_workflow_timeout.py +0 -0
  39. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/933e86bdac6a_add_queue_priority.py +0 -0
  40. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/a3b18ad34abe_added_triggers.py +0 -0
  41. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/d76646551a6b_job_queue_limiter.py +0 -0
  42. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/d76646551a6c_workflow_queue.py +0 -0
  43. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/d994145b47b6_consolidate_inputs.py +0 -0
  44. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/eab0cc1d9a14_job_queue.py +0 -0
  45. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_migrations/versions/f4b9b32ba814_functionname_childid_op_outputs.py +0 -0
  46. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_outcome.py +0 -0
  47. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_queue.py +0 -0
  48. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_roles.py +0 -0
  49. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_scheduler.py +0 -0
  50. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_schemas/__init__.py +0 -0
  51. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_schemas/application_database.py +0 -0
  52. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_schemas/system_database.py +0 -0
  53. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_serialization.py +0 -0
  54. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_sys_db.py +0 -0
  55. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/README.md +0 -0
  56. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/__package/__init__.py +0 -0
  57. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/__package/main.py.dbos +0 -0
  58. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/__package/schema.py +0 -0
  59. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/alembic.ini +0 -0
  60. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/dbos-config.yaml.dbos +0 -0
  61. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/migrations/env.py.dbos +0 -0
  62. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/migrations/script.py.mako +0 -0
  63. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/migrations/versions/2024_07_31_180642_init.py +0 -0
  64. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_templates/dbos-db-starter/start_postgres_docker.py +0 -0
  65. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_tracer.py +0 -0
  66. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_utils.py +0 -0
  67. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/_workflow_commands.py +0 -0
  68. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/cli/_github_init.py +0 -0
  69. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/cli/_template_init.py +0 -0
  70. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/cli/cli.py +0 -0
  71. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/cli/migration.py +0 -0
  72. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/dbos-config.schema.json +0 -0
  73. {dbos-1.11.0a6 → dbos-1.12.0a1}/dbos/py.typed +0 -0
  74. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/__init__.py +0 -0
  75. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/atexit_no_ctor.py +0 -0
  76. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/atexit_no_launch.py +0 -0
  77. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/classdefs.py +0 -0
  78. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/client_collateral.py +0 -0
  79. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/client_worker.py +0 -0
  80. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/conftest.py +0 -0
  81. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/dupname_classdefs1.py +0 -0
  82. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/dupname_classdefsa.py +0 -0
  83. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/more_classdefs.py +0 -0
  84. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/queuedworkflow.py +0 -0
  85. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_admin_server.py +0 -0
  86. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_async.py +0 -0
  87. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_async_workflow_management.py +0 -0
  88. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_classdecorators.py +0 -0
  89. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_cli.py +0 -0
  90. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_client.py +0 -0
  91. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_concurrency.py +0 -0
  92. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_config.py +0 -0
  93. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_croniter.py +0 -0
  94. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_dbos.py +0 -0
  95. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_debug.py +0 -0
  96. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_docker_secrets.py +0 -0
  97. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_fastapi.py +0 -0
  98. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_fastapi_roles.py +0 -0
  99. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_flask.py +0 -0
  100. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_kafka.py +0 -0
  101. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_migrate.py +0 -0
  102. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_outcome.py +0 -0
  103. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_package.py +0 -0
  104. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_queue.py +0 -0
  105. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_scheduler.py +0 -0
  106. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_schema_migration.py +0 -0
  107. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_singleton.py +0 -0
  108. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_spans.py +0 -0
  109. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_sqlalchemy.py +0 -0
  110. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_streaming.py +0 -0
  111. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_workflow_introspection.py +0 -0
  112. {dbos-1.11.0a6 → dbos-1.12.0a1}/tests/test_workflow_management.py +0 -0
  113. {dbos-1.11.0a6 → dbos-1.12.0a1}/version/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 1.11.0a6
3
+ Version: 1.12.0a1
4
4
  Summary: Ultra-lightweight durable execution in Python
5
5
  Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
6
  License: MIT
@@ -753,3 +753,34 @@ class DBOSAssumeRole:
753
753
  assert ctx.assumed_role == self.assume_role
754
754
  ctx.assumed_role = self.prior_role
755
755
  return False # Did not handle
756
+
757
+
758
+ class UseLogAttributes:
759
+ """Temporarily set context attributes for logging"""
760
+
761
+ def __init__(self, *, workflow_id: str = "") -> None:
762
+ self.workflow_id = workflow_id
763
+ self.created_ctx = False
764
+
765
+ def __enter__(self) -> UseLogAttributes:
766
+ ctx = get_local_dbos_context()
767
+ if ctx is None:
768
+ self.created_ctx = True
769
+ _set_local_dbos_context(DBOSContext())
770
+ ctx = assert_current_dbos_context()
771
+ self.saved_workflow_id = ctx.workflow_id
772
+ ctx.workflow_id = self.workflow_id
773
+ return self
774
+
775
+ def __exit__(
776
+ self,
777
+ exc_type: Optional[Type[BaseException]],
778
+ exc_value: Optional[BaseException],
779
+ traceback: Optional[TracebackType],
780
+ ) -> Literal[False]:
781
+ ctx = assert_current_dbos_context()
782
+ ctx.workflow_id = self.saved_workflow_id
783
+ # Clean up the basic context if we created it
784
+ if self.created_ctx:
785
+ _clear_local_dbos_context()
786
+ return False # Did not handle
@@ -5,7 +5,6 @@ import json
5
5
  import sys
6
6
  import threading
7
7
  import time
8
- import traceback
9
8
  from concurrent.futures import Future
10
9
  from functools import wraps
11
10
  from typing import (
@@ -66,7 +65,6 @@ from ._registrations import (
66
65
  get_dbos_func_name,
67
66
  get_func_info,
68
67
  get_or_create_func_info,
69
- get_temp_workflow_type,
70
68
  set_dbos_func_name,
71
69
  set_func_info,
72
70
  set_temp_workflow_type,
@@ -452,7 +450,7 @@ def execute_workflow_by_id(dbos: "DBOS", workflow_id: str) -> "WorkflowHandle[An
452
450
  if not wf_func:
453
451
  raise DBOSWorkflowFunctionNotFoundError(
454
452
  workflow_id,
455
- f"Cannot execute workflow because {status['name']} is not a registered workflow function",
453
+ f"{status['name']} is not a registered workflow function",
456
454
  )
457
455
  with DBOSContextEnsure():
458
456
  # If this function belongs to a configured class, add that class instance as its first argument
@@ -463,7 +461,7 @@ def execute_workflow_by_id(dbos: "DBOS", workflow_id: str) -> "WorkflowHandle[An
463
461
  if iname not in dbos._registry.instance_info_map:
464
462
  raise DBOSWorkflowFunctionNotFoundError(
465
463
  workflow_id,
466
- f"Cannot execute workflow because instance '{iname}' is not registered",
464
+ f"configured class instance '{iname}' is not registered",
467
465
  )
468
466
  class_instance = dbos._registry.instance_info_map[iname]
469
467
  inputs["args"] = (class_instance,) + inputs["args"]
@@ -473,7 +471,7 @@ def execute_workflow_by_id(dbos: "DBOS", workflow_id: str) -> "WorkflowHandle[An
473
471
  if class_name not in dbos._registry.class_info_map:
474
472
  raise DBOSWorkflowFunctionNotFoundError(
475
473
  workflow_id,
476
- f"Cannot execute workflow because class '{class_name}' is not registered",
474
+ f"class '{class_name}' is not registered",
477
475
  )
478
476
  class_object = dbos._registry.class_info_map[class_name]
479
477
  inputs["args"] = (class_object,) + inputs["args"]
@@ -534,7 +532,7 @@ def start_workflow(
534
532
  if fi is None:
535
533
  raise DBOSWorkflowFunctionNotFoundError(
536
534
  "<NONE>",
537
- f"start_workflow: function {func.__name__} is not registered",
535
+ f"{func.__name__} is not a registered workflow function",
538
536
  )
539
537
 
540
538
  func = cast("Workflow[P, R]", func.__orig_func) # type: ignore
@@ -630,7 +628,7 @@ async def start_workflow_async(
630
628
  if fi is None:
631
629
  raise DBOSWorkflowFunctionNotFoundError(
632
630
  "<NONE>",
633
- f"start_workflow: function {func.__name__} is not registered",
631
+ f"{func.__name__} is not a registered workflow function",
634
632
  )
635
633
 
636
634
  func = cast("Workflow[P, R]", func.__orig_func) # type: ignore
@@ -211,6 +211,10 @@ class DBOSRegistry:
211
211
  def register_instance(self, inst: object) -> None:
212
212
  config_name = getattr(inst, "config_name")
213
213
  class_name = _class_fqn(inst.__class__)
214
+ if self.dbos and self.dbos._launched:
215
+ dbos_logger.warning(
216
+ f"Configured instance {config_name} of class {class_name} was registered after DBOS was launched. This may cause errors during workflow recovery. All configured instances should be instantiated before DBOS is launched."
217
+ )
214
218
  fn = f"{class_name}/{config_name}"
215
219
  if fn in self.instance_info_map:
216
220
  if self.instance_info_map[fn] is not inst:
@@ -106,7 +106,7 @@ class DBOSWorkflowFunctionNotFoundError(DBOSException):
106
106
 
107
107
  def __init__(self, workflow_id: str, message: Optional[str] = None):
108
108
  super().__init__(
109
- f"Workflow function not found for workflow ID {workflow_id}: {message}",
109
+ f"Could not execute workflow {workflow_id}: {message}",
110
110
  dbos_error_code=DBOSErrorCode.WorkflowFunctionNotFound.value,
111
111
  )
112
112
 
@@ -2,6 +2,7 @@ import threading
2
2
  import time
3
3
  from typing import TYPE_CHECKING, Any, List
4
4
 
5
+ from dbos._context import UseLogAttributes
5
6
  from dbos._utils import GlobalParams
6
7
 
7
8
  from ._core import execute_workflow_by_id
@@ -29,17 +30,19 @@ def startup_recovery_thread(
29
30
  stop_event = threading.Event()
30
31
  dbos.background_thread_stop_events.append(stop_event)
31
32
  while not stop_event.is_set() and len(pending_workflows) > 0:
32
- try:
33
- for pending_workflow in list(pending_workflows):
33
+ for pending_workflow in list(pending_workflows):
34
+ try:
34
35
  _recover_workflow(dbos, pending_workflow)
35
36
  pending_workflows.remove(pending_workflow)
36
- except DBOSWorkflowFunctionNotFoundError:
37
- time.sleep(1)
38
- except Exception as e:
39
- dbos.logger.error(
40
- f"Exception encountered when recovering workflows:", exc_info=e
41
- )
42
- raise
37
+ except DBOSWorkflowFunctionNotFoundError:
38
+ time.sleep(1)
39
+ except Exception as e:
40
+ with UseLogAttributes(workflow_id=pending_workflow.workflow_uuid):
41
+ dbos.logger.error(
42
+ f"Exception encountered when recovering workflow {pending_workflow.workflow_uuid}:",
43
+ exc_info=e,
44
+ )
45
+ raise
43
46
 
44
47
 
45
48
  def recover_pending_workflows(
@@ -56,9 +59,11 @@ def recover_pending_workflows(
56
59
  handle = _recover_workflow(dbos, pending_workflow)
57
60
  workflow_handles.append(handle)
58
61
  except Exception as e:
59
- dbos.logger.error(
60
- f"Exception encountered when recovering workflows:", exc_info=e
61
- )
62
+ with UseLogAttributes(workflow_id=pending_workflow.workflow_uuid):
63
+ dbos.logger.error(
64
+ f"Exception encountered when recovering workflow {pending_workflow.workflow_uuid}:",
65
+ exc_info=e,
66
+ )
62
67
  raise
63
68
  dbos.logger.info(
64
69
  f"Recovering {len(pending_workflows)} workflows for executor {executor_id} from version {GlobalParams.app_version}"
@@ -13,7 +13,7 @@ def get_dbos_func_name(f: Any) -> str:
13
13
  if hasattr(f, "dbos_function_name"):
14
14
  return str(getattr(f, "dbos_function_name"))
15
15
  raise DBOSWorkflowFunctionNotFoundError(
16
- "<NONE>", f"function {f.__name__} is not registered"
16
+ "<NONE>", f"{f.__name__} is not a registered workflow function"
17
17
  )
18
18
 
19
19
 
@@ -27,7 +27,7 @@ dependencies = [
27
27
  ]
28
28
  requires-python = ">=3.9"
29
29
  readme = "README.md"
30
- version = "1.11.0a6"
30
+ version = "1.12.0a1"
31
31
 
32
32
  [project.license]
33
33
  text = "MIT"
@@ -8,12 +8,14 @@ from psycopg.errors import SerializationFailure
8
8
  from sqlalchemy.exc import InvalidRequestError, OperationalError
9
9
 
10
10
  from dbos import DBOS, Queue, SetWorkflowID
11
+ from dbos._dbos_config import DBOSConfig
11
12
  from dbos._error import (
12
13
  DBOSAwaitedWorkflowCancelledError,
13
14
  DBOSMaxStepRetriesExceeded,
14
15
  DBOSNotAuthorizedError,
15
16
  DBOSQueueDeduplicatedError,
16
17
  DBOSUnexpectedStepError,
18
+ DBOSWorkflowFunctionNotFoundError,
17
19
  MaxRecoveryAttemptsExceededError,
18
20
  )
19
21
  from dbos._registrations import DEFAULT_MAX_RECOVERY_ATTEMPTS
@@ -499,3 +501,24 @@ def test_error_serialization() -> None:
499
501
  assert output is None
500
502
  assert isinstance(exception, str)
501
503
  assert "Message: 1, 2" in exception
504
+
505
+
506
+ def test_unregistered_workflow(dbos: DBOS, config: DBOSConfig) -> None:
507
+
508
+ @DBOS.workflow()
509
+ def workflow() -> None:
510
+ return
511
+
512
+ wfid = str(uuid.uuid4())
513
+ with SetWorkflowID(wfid):
514
+ workflow()
515
+
516
+ dbos._sys_db.update_workflow_outcome(wfid, "PENDING")
517
+
518
+ DBOS.destroy(destroy_registry=True)
519
+ config["executor_id"] = str(uuid.uuid4())
520
+ DBOS(config=config)
521
+ DBOS.launch()
522
+
523
+ with pytest.raises(DBOSWorkflowFunctionNotFoundError):
524
+ DBOS._recover_pending_workflows()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes