dbos 1.8.0a8__tar.gz → 1.9.0__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.
- {dbos-1.8.0a8 → dbos-1.9.0}/PKG-INFO +1 -1
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_core.py +2 -1
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_dbos.py +25 -25
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/cli/cli.py +6 -6
- {dbos-1.8.0a8 → dbos-1.9.0}/pyproject.toml +1 -1
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_admin_server.py +12 -7
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_async.py +9 -7
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_async_workflow_management.py +3 -3
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_classdecorators.py +27 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_concurrency.py +9 -3
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_dbos.py +40 -20
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_failures.py +8 -4
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_fastapi.py +3 -1
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_flask.py +3 -1
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_queue.py +11 -6
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_scheduler.py +3 -1
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_workflow_introspection.py +27 -9
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_workflow_management.py +10 -6
- {dbos-1.8.0a8 → dbos-1.9.0}/LICENSE +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/README.md +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/__init__.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/__main__.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_admin_server.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_app_db.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_classproperty.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_client.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_conductor/conductor.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_conductor/protocol.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_context.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_croniter.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_dbos_config.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_debug.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_docker_pg_helper.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_error.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_event_loop.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_fastapi.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_flask.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_kafka.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_kafka_message.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_logger.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/env.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/script.py.mako +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/04ca4f231047_workflow_queues_executor_id.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/27ac6900c6ad_add_queue_dedup.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/50f3227f0b4b_fix_job_queue.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/5c361fc04708_added_system_tables.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/66478e1b95e5_consolidate_queues.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/83f3732ae8e7_workflow_timeout.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/933e86bdac6a_add_queue_priority.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/a3b18ad34abe_added_triggers.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/d76646551a6b_job_queue_limiter.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/d76646551a6c_workflow_queue.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/d994145b47b6_consolidate_inputs.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/eab0cc1d9a14_job_queue.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/f4b9b32ba814_functionname_childid_op_outputs.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_outcome.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_queue.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_recovery.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_registrations.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_roles.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_scheduler.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_schemas/__init__.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_schemas/application_database.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_schemas/system_database.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_serialization.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_sys_db.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/README.md +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/__package/__init__.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/__package/main.py.dbos +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/__package/schema.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/alembic.ini +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/dbos-config.yaml.dbos +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/migrations/env.py.dbos +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/migrations/script.py.mako +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/migrations/versions/2024_07_31_180642_init.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_templates/dbos-db-starter/start_postgres_docker.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_tracer.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_utils.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/_workflow_commands.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/cli/_github_init.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/cli/_template_init.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/dbos-config.schema.json +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/dbos/py.typed +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/__init__.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/atexit_no_ctor.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/atexit_no_launch.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/classdefs.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/client_collateral.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/client_worker.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/conftest.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/dupname_classdefs1.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/dupname_classdefsa.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/more_classdefs.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/queuedworkflow.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_cli.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_client.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_config.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_croniter.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_debug.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_docker_secrets.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_fastapi_roles.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_kafka.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_outcome.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_package.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_schema_migration.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_singleton.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_spans.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/tests/test_sqlalchemy.py +0 -0
- {dbos-1.8.0a8 → dbos-1.9.0}/version/__init__.py +0 -0
|
@@ -49,6 +49,7 @@ from ._context import (
|
|
|
49
49
|
get_local_dbos_context,
|
|
50
50
|
)
|
|
51
51
|
from ._error import (
|
|
52
|
+
DBOSAwaitedWorkflowCancelledError,
|
|
52
53
|
DBOSException,
|
|
53
54
|
DBOSMaxStepRetriesExceeded,
|
|
54
55
|
DBOSNonExistentWorkflowError,
|
|
@@ -370,7 +371,7 @@ def _get_wf_invoke_func(
|
|
|
370
371
|
r: R = dbos._sys_db.await_workflow_result(status["workflow_uuid"])
|
|
371
372
|
return r
|
|
372
373
|
except DBOSWorkflowCancelledError as error:
|
|
373
|
-
raise
|
|
374
|
+
raise DBOSAwaitedWorkflowCancelledError(status["workflow_uuid"])
|
|
374
375
|
except Exception as error:
|
|
375
376
|
if not dbos.debug_mode:
|
|
376
377
|
dbos._sys_db.update_workflow_outcome(
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
import atexit
|
|
5
4
|
import hashlib
|
|
6
5
|
import inspect
|
|
7
6
|
import os
|
|
@@ -1219,39 +1218,40 @@ class DBOS:
|
|
|
1219
1218
|
return rv
|
|
1220
1219
|
|
|
1221
1220
|
@classproperty
|
|
1222
|
-
def workflow_id(cls) -> str:
|
|
1223
|
-
"""Return the
|
|
1224
|
-
ctx =
|
|
1225
|
-
|
|
1226
|
-
ctx.
|
|
1227
|
-
|
|
1228
|
-
|
|
1221
|
+
def workflow_id(cls) -> Optional[str]:
|
|
1222
|
+
"""Return the ID of the currently executing workflow. If a workflow is not executing, return None."""
|
|
1223
|
+
ctx = get_local_dbos_context()
|
|
1224
|
+
if ctx and ctx.is_within_workflow():
|
|
1225
|
+
return ctx.workflow_id
|
|
1226
|
+
else:
|
|
1227
|
+
return None
|
|
1229
1228
|
|
|
1230
1229
|
@classproperty
|
|
1231
|
-
def step_id(cls) -> int:
|
|
1232
|
-
"""Return the step ID for the currently executing step. This is a unique identifier of the current step within the workflow."""
|
|
1233
|
-
ctx =
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1230
|
+
def step_id(cls) -> Optional[int]:
|
|
1231
|
+
"""Return the step ID for the currently executing step. This is a unique identifier of the current step within the workflow. If a step is not currently executing, return None."""
|
|
1232
|
+
ctx = get_local_dbos_context()
|
|
1233
|
+
if ctx and (ctx.is_step() or ctx.is_transaction()):
|
|
1234
|
+
return ctx.function_id
|
|
1235
|
+
else:
|
|
1236
|
+
return None
|
|
1238
1237
|
|
|
1239
1238
|
@classproperty
|
|
1240
|
-
def step_status(cls) -> StepStatus:
|
|
1241
|
-
"""Return the status of the currently executing step."""
|
|
1242
|
-
ctx =
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1239
|
+
def step_status(cls) -> Optional[StepStatus]:
|
|
1240
|
+
"""Return the status of the currently executing step. If a step is not currently executing, return None."""
|
|
1241
|
+
ctx = get_local_dbos_context()
|
|
1242
|
+
if ctx and ctx.is_step():
|
|
1243
|
+
return ctx.step_status
|
|
1244
|
+
else:
|
|
1245
|
+
return None
|
|
1246
1246
|
|
|
1247
1247
|
@classproperty
|
|
1248
1248
|
def parent_workflow_id(cls) -> str:
|
|
1249
1249
|
"""
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
`parent_workflow_id` must be accessed from within a workflow function.
|
|
1250
|
+
This method is deprecated and should not be used.
|
|
1253
1251
|
"""
|
|
1254
|
-
|
|
1252
|
+
dbos_logger.warning(
|
|
1253
|
+
"DBOS.parent_workflow_id is deprecated and should not be used"
|
|
1254
|
+
)
|
|
1255
1255
|
ctx = assert_current_dbos_context()
|
|
1256
1256
|
assert (
|
|
1257
1257
|
ctx.is_within_workflow()
|
|
@@ -10,7 +10,7 @@ from typing import Any, Optional
|
|
|
10
10
|
import jsonpickle # type: ignore
|
|
11
11
|
import sqlalchemy as sa
|
|
12
12
|
import typer
|
|
13
|
-
from rich import print
|
|
13
|
+
from rich import print as richprint
|
|
14
14
|
from rich.prompt import IntPrompt
|
|
15
15
|
from typing_extensions import Annotated, List
|
|
16
16
|
|
|
@@ -196,7 +196,7 @@ def init(
|
|
|
196
196
|
path.join(templates_dir, template), project_name, config_mode=config
|
|
197
197
|
)
|
|
198
198
|
except Exception as e:
|
|
199
|
-
|
|
199
|
+
richprint(f"[red]{e}[/red]")
|
|
200
200
|
|
|
201
201
|
|
|
202
202
|
def _resolve_project_name_and_template(
|
|
@@ -217,9 +217,9 @@ def _resolve_project_name_and_template(
|
|
|
217
217
|
if template not in templates:
|
|
218
218
|
raise Exception(f"Template {template} not found in {templates_dir}")
|
|
219
219
|
else:
|
|
220
|
-
|
|
220
|
+
richprint("\n[bold]Available templates:[/bold]")
|
|
221
221
|
for idx, template_name in enumerate(templates, 1):
|
|
222
|
-
|
|
222
|
+
richprint(f" {idx}. {template_name}")
|
|
223
223
|
while True:
|
|
224
224
|
try:
|
|
225
225
|
choice = IntPrompt.ask(
|
|
@@ -231,13 +231,13 @@ def _resolve_project_name_and_template(
|
|
|
231
231
|
template = templates[choice - 1]
|
|
232
232
|
break
|
|
233
233
|
else:
|
|
234
|
-
|
|
234
|
+
richprint(
|
|
235
235
|
"[red]Invalid selection. Please choose a number from the list.[/red]"
|
|
236
236
|
)
|
|
237
237
|
except (KeyboardInterrupt, EOFError):
|
|
238
238
|
raise typer.Abort()
|
|
239
239
|
except ValueError:
|
|
240
|
-
|
|
240
|
+
richprint("[red]Please enter a valid number.[/red]")
|
|
241
241
|
|
|
242
242
|
if template in git_templates:
|
|
243
243
|
if project_name is None:
|
|
@@ -20,7 +20,7 @@ from dbos import (
|
|
|
20
20
|
WorkflowHandle,
|
|
21
21
|
_workflow_commands,
|
|
22
22
|
)
|
|
23
|
-
from dbos._error import
|
|
23
|
+
from dbos._error import DBOSAwaitedWorkflowCancelledError
|
|
24
24
|
from dbos._schemas.system_database import SystemSchema
|
|
25
25
|
from dbos._sys_db import SystemDatabase, WorkflowStatusString
|
|
26
26
|
from dbos._utils import INTERNAL_QUEUE_NAME, GlobalParams
|
|
@@ -142,7 +142,6 @@ def test_admin_recovery(config: DBOSConfig) -> None:
|
|
|
142
142
|
|
|
143
143
|
@DBOS.workflow()
|
|
144
144
|
def test_workflow(var: str, var2: str) -> str:
|
|
145
|
-
DBOS.logger.info("WFID: " + DBOS.workflow_id)
|
|
146
145
|
nonlocal wf_counter
|
|
147
146
|
wf_counter += 1
|
|
148
147
|
res = test_step(var2)
|
|
@@ -307,7 +306,7 @@ def test_admin_workflow_resume(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
|
307
306
|
)
|
|
308
307
|
assert response.status_code == 204
|
|
309
308
|
event.set()
|
|
310
|
-
with pytest.raises(
|
|
309
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
311
310
|
handle.get_result()
|
|
312
311
|
info = _workflow_commands.get_workflow(sys_db, wfid)
|
|
313
312
|
assert info is not None
|
|
@@ -464,7 +463,9 @@ def test_list_workflows(dbos: DBOS) -> None:
|
|
|
464
463
|
|
|
465
464
|
@DBOS.workflow()
|
|
466
465
|
def test_workflow_2(my_time: datetime) -> str:
|
|
467
|
-
|
|
466
|
+
workflow_id = DBOS.workflow_id
|
|
467
|
+
assert workflow_id is not None
|
|
468
|
+
return workflow_id + " completed at " + my_time.isoformat()
|
|
468
469
|
|
|
469
470
|
# Start workflows
|
|
470
471
|
handle_1 = DBOS.start_workflow(test_workflow_1)
|
|
@@ -656,7 +657,9 @@ def test_get_workflow_by_id(dbos: DBOS) -> None:
|
|
|
656
657
|
|
|
657
658
|
@DBOS.workflow()
|
|
658
659
|
def test_workflow_2(my_time: datetime) -> str:
|
|
659
|
-
|
|
660
|
+
workflow_id = DBOS.workflow_id
|
|
661
|
+
assert workflow_id is not None
|
|
662
|
+
return workflow_id + " completed at " + my_time.isoformat()
|
|
660
663
|
|
|
661
664
|
# Start workflows
|
|
662
665
|
handle_1 = DBOS.start_workflow(test_workflow_1)
|
|
@@ -713,7 +716,9 @@ def test_admin_garbage_collect(dbos: DBOS) -> None:
|
|
|
713
716
|
|
|
714
717
|
@DBOS.workflow()
|
|
715
718
|
def workflow() -> str:
|
|
716
|
-
|
|
719
|
+
workflow_id = DBOS.workflow_id
|
|
720
|
+
assert workflow_id is not None
|
|
721
|
+
return workflow_id
|
|
717
722
|
|
|
718
723
|
workflow()
|
|
719
724
|
|
|
@@ -745,7 +750,7 @@ def test_admin_global_timeout(dbos: DBOS) -> None:
|
|
|
745
750
|
timeout=5,
|
|
746
751
|
)
|
|
747
752
|
response.raise_for_status()
|
|
748
|
-
with pytest.raises(
|
|
753
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
749
754
|
handle.get_result()
|
|
750
755
|
|
|
751
756
|
|
|
@@ -18,7 +18,7 @@ from dbos import (
|
|
|
18
18
|
from dbos._context import assert_current_dbos_context
|
|
19
19
|
from dbos._dbos import WorkflowHandle
|
|
20
20
|
from dbos._dbos_config import ConfigFile
|
|
21
|
-
from dbos._error import
|
|
21
|
+
from dbos._error import DBOSAwaitedWorkflowCancelledError, DBOSException
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@pytest.mark.asyncio
|
|
@@ -302,7 +302,9 @@ async def test_sleep(dbos: DBOS) -> None:
|
|
|
302
302
|
@DBOS.workflow()
|
|
303
303
|
async def test_sleep_workflow(secs: float) -> str:
|
|
304
304
|
await dbos.sleep_async(secs)
|
|
305
|
-
|
|
305
|
+
workflow_id = DBOS.workflow_id
|
|
306
|
+
assert workflow_id is not None
|
|
307
|
+
return workflow_id
|
|
306
308
|
|
|
307
309
|
start_time = time.time()
|
|
308
310
|
sleep_uuid = await test_sleep_workflow(1.5)
|
|
@@ -490,20 +492,20 @@ async def test_workflow_timeout_async(dbos: DBOS) -> None:
|
|
|
490
492
|
DBOS.sleep(0.1)
|
|
491
493
|
|
|
492
494
|
with SetWorkflowTimeout(0.1):
|
|
493
|
-
with pytest.raises(
|
|
495
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
494
496
|
await blocked_workflow()
|
|
495
497
|
handle = await DBOS.start_workflow_async(blocked_workflow)
|
|
496
|
-
with pytest.raises(
|
|
498
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
497
499
|
await handle.get_result()
|
|
498
500
|
|
|
499
501
|
@DBOS.workflow()
|
|
500
502
|
async def parent_workflow_with_timeout() -> None:
|
|
501
503
|
assert assert_current_dbos_context().workflow_deadline_epoch_ms is None
|
|
502
504
|
with SetWorkflowTimeout(0.1):
|
|
503
|
-
with pytest.raises(
|
|
505
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
504
506
|
await blocked_workflow()
|
|
505
507
|
handle = await DBOS.start_workflow_async(blocked_workflow)
|
|
506
|
-
with pytest.raises(
|
|
508
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
507
509
|
await handle.get_result()
|
|
508
510
|
assert assert_current_dbos_context().workflow_deadline_epoch_ms is None
|
|
509
511
|
|
|
@@ -524,7 +526,7 @@ async def test_workflow_timeout_async(dbos: DBOS) -> None:
|
|
|
524
526
|
# Verify if a parent called with a timeout calls a blocked child
|
|
525
527
|
# the deadline propagates and the children are also cancelled.
|
|
526
528
|
with SetWorkflowTimeout(1.0):
|
|
527
|
-
with pytest.raises(
|
|
529
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
528
530
|
await parent_workflow()
|
|
529
531
|
|
|
530
532
|
with pytest.raises(Exception) as exc_info:
|
|
@@ -7,7 +7,7 @@ from typing import List
|
|
|
7
7
|
import pytest
|
|
8
8
|
|
|
9
9
|
from dbos import DBOS, Queue, SetWorkflowID
|
|
10
|
-
from dbos._error import
|
|
10
|
+
from dbos._error import DBOSAwaitedWorkflowCancelledError
|
|
11
11
|
from dbos._sys_db import StepInfo, WorkflowStatus
|
|
12
12
|
from tests.conftest import queue_entries_are_cleaned_up
|
|
13
13
|
|
|
@@ -46,7 +46,7 @@ async def test_cancel_workflow_async(dbos: DBOS) -> None:
|
|
|
46
46
|
await DBOS.cancel_workflow_async(wfid)
|
|
47
47
|
workflow_event.set()
|
|
48
48
|
|
|
49
|
-
with pytest.raises(
|
|
49
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
50
50
|
handle.get_result()
|
|
51
51
|
assert steps_completed == 1
|
|
52
52
|
|
|
@@ -85,7 +85,7 @@ async def test_resume_workflow_async(dbos: DBOS) -> None:
|
|
|
85
85
|
DBOS.cancel_workflow(wfid)
|
|
86
86
|
workflow_event.set()
|
|
87
87
|
|
|
88
|
-
with pytest.raises(
|
|
88
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
89
89
|
handle.get_result()
|
|
90
90
|
assert steps_completed == 1
|
|
91
91
|
|
|
@@ -911,3 +911,30 @@ def test_class_step_without_dbos(dbos: DBOS, config: DBOSConfig) -> None:
|
|
|
911
911
|
DBOS.launch()
|
|
912
912
|
|
|
913
913
|
assert inst.step(input) == input + input
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
def test_class_with_only_steps(dbos: DBOS) -> None:
|
|
917
|
+
|
|
918
|
+
class StepClass:
|
|
919
|
+
def __init__(self, x: int) -> None:
|
|
920
|
+
self.x = x
|
|
921
|
+
|
|
922
|
+
@DBOS.step()
|
|
923
|
+
def step(self, x: int, expr: Callable[[int, int], int]) -> int:
|
|
924
|
+
return expr(self.x, x)
|
|
925
|
+
|
|
926
|
+
input = 5
|
|
927
|
+
inst = StepClass(5)
|
|
928
|
+
|
|
929
|
+
l = lambda x, y: x + y
|
|
930
|
+
|
|
931
|
+
@DBOS.workflow()
|
|
932
|
+
def test_workflow() -> int:
|
|
933
|
+
return inst.step(input, l) + inst.step(input, l)
|
|
934
|
+
|
|
935
|
+
handle = DBOS.start_workflow(test_workflow)
|
|
936
|
+
assert handle.get_result() == input * 4
|
|
937
|
+
|
|
938
|
+
steps = DBOS.list_workflow_steps(handle.workflow_id)
|
|
939
|
+
assert len(steps) == 2
|
|
940
|
+
assert steps[1]["output"] == steps[1]["output"] == input * 2
|
|
@@ -14,7 +14,9 @@ def test_concurrent_workflows(dbos: DBOS) -> None:
|
|
|
14
14
|
@DBOS.workflow()
|
|
15
15
|
def test_workflow() -> str:
|
|
16
16
|
time.sleep(1)
|
|
17
|
-
|
|
17
|
+
workflow_id = DBOS.workflow_id
|
|
18
|
+
assert workflow_id is not None
|
|
19
|
+
return workflow_id
|
|
18
20
|
|
|
19
21
|
def test_thread(id: str) -> str:
|
|
20
22
|
with SetWorkflowID(id):
|
|
@@ -48,7 +50,9 @@ def test_concurrent_conflict_uuid(dbos: DBOS) -> None:
|
|
|
48
50
|
condition.notify()
|
|
49
51
|
condition.release()
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
workflow_id = DBOS.workflow_id
|
|
54
|
+
assert workflow_id is not None
|
|
55
|
+
return workflow_id
|
|
52
56
|
|
|
53
57
|
@DBOS.workflow()
|
|
54
58
|
def test_workflow() -> str:
|
|
@@ -74,7 +78,9 @@ def test_concurrent_conflict_uuid(dbos: DBOS) -> None:
|
|
|
74
78
|
condition.notify()
|
|
75
79
|
condition.release()
|
|
76
80
|
|
|
77
|
-
|
|
81
|
+
workflow_id = DBOS.workflow_id
|
|
82
|
+
assert workflow_id is not None
|
|
83
|
+
return workflow_id
|
|
78
84
|
|
|
79
85
|
def test_txn_thread(id: str) -> str:
|
|
80
86
|
with SetWorkflowID(id):
|
|
@@ -28,7 +28,6 @@ from dbos._error import (
|
|
|
28
28
|
DBOSAwaitedWorkflowCancelledError,
|
|
29
29
|
DBOSConflictingRegistrationError,
|
|
30
30
|
DBOSMaxStepRetriesExceeded,
|
|
31
|
-
DBOSWorkflowCancelledError,
|
|
32
31
|
)
|
|
33
32
|
from dbos._schemas.system_database import SystemSchema
|
|
34
33
|
from dbos._sys_db import GetWorkflowsInput
|
|
@@ -61,9 +60,11 @@ def test_simple_workflow(dbos: DBOS) -> None:
|
|
|
61
60
|
@DBOS.step()
|
|
62
61
|
def test_step(var: str) -> str:
|
|
63
62
|
assert DBOS.step_id == 2
|
|
64
|
-
|
|
65
|
-
assert
|
|
66
|
-
assert
|
|
63
|
+
step_status = DBOS.step_status
|
|
64
|
+
assert step_status is not None
|
|
65
|
+
assert step_status.step_id == 2
|
|
66
|
+
assert step_status.current_attempt is None
|
|
67
|
+
assert step_status.max_attempts is None
|
|
67
68
|
nonlocal step_counter
|
|
68
69
|
step_counter += 1
|
|
69
70
|
DBOS.logger.info("I'm test_step " + var)
|
|
@@ -133,10 +134,6 @@ def test_child_workflow(dbos: DBOS) -> None:
|
|
|
133
134
|
@DBOS.workflow()
|
|
134
135
|
def test_workflow(var: str, var2: str) -> str:
|
|
135
136
|
DBOS.logger.info("I'm test_workflow")
|
|
136
|
-
if len(DBOS.parent_workflow_id):
|
|
137
|
-
DBOS.logger.info(" This is a child test_workflow")
|
|
138
|
-
# Note this assertion is only true if child wasn't assigned an ID explicitly
|
|
139
|
-
assert DBOS.workflow_id.startswith(DBOS.parent_workflow_id)
|
|
140
137
|
nonlocal wf_counter
|
|
141
138
|
wf_counter += 1
|
|
142
139
|
res = test_transaction(var2)
|
|
@@ -651,7 +648,9 @@ def test_retrieve_workflow(dbos: DBOS) -> None:
|
|
|
651
648
|
@DBOS.workflow()
|
|
652
649
|
def test_sleep_workflow(secs: float) -> str:
|
|
653
650
|
dbos.sleep(secs)
|
|
654
|
-
|
|
651
|
+
workflow_id = DBOS.workflow_id
|
|
652
|
+
assert workflow_id is not None
|
|
653
|
+
return workflow_id
|
|
655
654
|
|
|
656
655
|
@DBOS.workflow()
|
|
657
656
|
def test_sleep_workthrow(secs: float) -> str:
|
|
@@ -732,7 +731,9 @@ def test_retrieve_workflow_in_workflow(dbos: DBOS) -> None:
|
|
|
732
731
|
@DBOS.workflow()
|
|
733
732
|
def test_sleep_workflow(secs: float) -> str:
|
|
734
733
|
dbos.sleep(secs)
|
|
735
|
-
|
|
734
|
+
workflow_id = DBOS.workflow_id
|
|
735
|
+
assert workflow_id is not None
|
|
736
|
+
return workflow_id
|
|
736
737
|
|
|
737
738
|
@DBOS.workflow()
|
|
738
739
|
def test_workflow_status_a() -> str:
|
|
@@ -793,7 +794,9 @@ def test_sleep(dbos: DBOS) -> None:
|
|
|
793
794
|
@DBOS.workflow()
|
|
794
795
|
def test_sleep_workflow(secs: float) -> str:
|
|
795
796
|
dbos.sleep(secs)
|
|
796
|
-
|
|
797
|
+
workflow_id = DBOS.workflow_id
|
|
798
|
+
assert workflow_id is not None
|
|
799
|
+
return workflow_id
|
|
797
800
|
|
|
798
801
|
start_time = time.time()
|
|
799
802
|
sleep_uuid = test_sleep_workflow(1.5)
|
|
@@ -1489,7 +1492,7 @@ def test_workflow_timeout(dbos: DBOS) -> None:
|
|
|
1489
1492
|
# Verify a blocked workflow called with a timeout is cancelled
|
|
1490
1493
|
wfid = str(uuid.uuid4())
|
|
1491
1494
|
with SetWorkflowTimeout(0.1):
|
|
1492
|
-
with pytest.raises(
|
|
1495
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
1493
1496
|
with SetWorkflowID(wfid):
|
|
1494
1497
|
blocked_workflow()
|
|
1495
1498
|
assert assert_current_dbos_context().workflow_deadline_epoch_ms is None
|
|
@@ -1501,7 +1504,7 @@ def test_workflow_timeout(dbos: DBOS) -> None:
|
|
|
1501
1504
|
status.workflow_deadline_epoch_ms is not None
|
|
1502
1505
|
and status.workflow_deadline_epoch_ms > start_time
|
|
1503
1506
|
)
|
|
1504
|
-
with pytest.raises(
|
|
1507
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
1505
1508
|
handle.get_result()
|
|
1506
1509
|
|
|
1507
1510
|
# Change the workflow status to pending
|
|
@@ -1514,17 +1517,17 @@ def test_workflow_timeout(dbos: DBOS) -> None:
|
|
|
1514
1517
|
# Recover the workflow, verify it still times out
|
|
1515
1518
|
handles = DBOS._recover_pending_workflows()
|
|
1516
1519
|
assert len(handles) == 1
|
|
1517
|
-
with pytest.raises(
|
|
1520
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
1518
1521
|
handles[0].get_result()
|
|
1519
1522
|
|
|
1520
1523
|
@DBOS.workflow()
|
|
1521
1524
|
def parent_workflow_with_timeout() -> None:
|
|
1522
1525
|
assert assert_current_dbos_context().workflow_deadline_epoch_ms is None
|
|
1523
1526
|
with SetWorkflowTimeout(0.1):
|
|
1524
|
-
with pytest.raises(
|
|
1527
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
1525
1528
|
blocked_workflow()
|
|
1526
1529
|
handle = DBOS.start_workflow(blocked_workflow)
|
|
1527
|
-
with pytest.raises(
|
|
1530
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
1528
1531
|
handle.get_result()
|
|
1529
1532
|
assert assert_current_dbos_context().workflow_deadline_epoch_ms is None
|
|
1530
1533
|
|
|
@@ -1545,7 +1548,7 @@ def test_workflow_timeout(dbos: DBOS) -> None:
|
|
|
1545
1548
|
# Verify if a parent called with a timeout calls a blocked child
|
|
1546
1549
|
# the deadline propagates and the children are also cancelled.
|
|
1547
1550
|
with SetWorkflowTimeout(1.0):
|
|
1548
|
-
with pytest.raises(
|
|
1551
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
1549
1552
|
parent_workflow()
|
|
1550
1553
|
|
|
1551
1554
|
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
@@ -1573,7 +1576,9 @@ def test_custom_names(dbos: DBOS) -> None:
|
|
|
1573
1576
|
|
|
1574
1577
|
@DBOS.workflow(name=workflow_name)
|
|
1575
1578
|
def workflow() -> str:
|
|
1576
|
-
|
|
1579
|
+
workflow_id = DBOS.workflow_id
|
|
1580
|
+
assert workflow_id is not None
|
|
1581
|
+
return workflow_id
|
|
1577
1582
|
|
|
1578
1583
|
handle = queue.enqueue(workflow)
|
|
1579
1584
|
assert handle.get_status().name == workflow_name
|
|
@@ -1581,7 +1586,9 @@ def test_custom_names(dbos: DBOS) -> None:
|
|
|
1581
1586
|
|
|
1582
1587
|
@DBOS.step(name=step_name)
|
|
1583
1588
|
def step() -> str:
|
|
1584
|
-
|
|
1589
|
+
workflow_id = DBOS.workflow_id
|
|
1590
|
+
assert workflow_id is not None
|
|
1591
|
+
return workflow_id
|
|
1585
1592
|
|
|
1586
1593
|
handle = queue.enqueue(step)
|
|
1587
1594
|
assert handle.get_status().name == f"<temp>.{step_name}"
|
|
@@ -1589,7 +1596,9 @@ def test_custom_names(dbos: DBOS) -> None:
|
|
|
1589
1596
|
|
|
1590
1597
|
@DBOS.transaction(name=txn_name)
|
|
1591
1598
|
def txn() -> str:
|
|
1592
|
-
|
|
1599
|
+
workflow_id = DBOS.workflow_id
|
|
1600
|
+
assert workflow_id is not None
|
|
1601
|
+
return workflow_id
|
|
1593
1602
|
|
|
1594
1603
|
handle = queue.enqueue(txn)
|
|
1595
1604
|
assert handle.get_status().name == f"<temp>.{txn_name}"
|
|
@@ -1614,12 +1623,22 @@ def test_custom_names(dbos: DBOS) -> None:
|
|
|
1614
1623
|
async def test_step_without_dbos(dbos: DBOS, config: DBOSConfig) -> None:
|
|
1615
1624
|
DBOS.destroy(destroy_registry=True)
|
|
1616
1625
|
|
|
1626
|
+
is_dbos_active = False
|
|
1627
|
+
|
|
1617
1628
|
@DBOS.step()
|
|
1618
1629
|
def step(x: int) -> int:
|
|
1630
|
+
if is_dbos_active:
|
|
1631
|
+
assert DBOS.workflow_id is not None
|
|
1632
|
+
else:
|
|
1633
|
+
assert DBOS.workflow_id is None
|
|
1619
1634
|
return x
|
|
1620
1635
|
|
|
1621
1636
|
@DBOS.step()
|
|
1622
1637
|
async def async_step(x: int) -> int:
|
|
1638
|
+
if is_dbos_active:
|
|
1639
|
+
assert DBOS.workflow_id is not None
|
|
1640
|
+
else:
|
|
1641
|
+
assert DBOS.workflow_id is None
|
|
1623
1642
|
return x
|
|
1624
1643
|
|
|
1625
1644
|
assert step(5) == 5
|
|
@@ -1631,6 +1650,7 @@ async def test_step_without_dbos(dbos: DBOS, config: DBOSConfig) -> None:
|
|
|
1631
1650
|
assert await async_step(5) == 5
|
|
1632
1651
|
|
|
1633
1652
|
DBOS.launch()
|
|
1653
|
+
is_dbos_active = True
|
|
1634
1654
|
|
|
1635
1655
|
assert step(5) == 5
|
|
1636
1656
|
assert await async_step(5) == 5
|
|
@@ -382,9 +382,11 @@ def test_step_status(dbos: DBOS) -> None:
|
|
|
382
382
|
@DBOS.step(retries_allowed=True, interval_seconds=0, max_attempts=max_attempts)
|
|
383
383
|
def failing_step() -> None:
|
|
384
384
|
nonlocal step_counter
|
|
385
|
-
|
|
386
|
-
assert
|
|
387
|
-
assert
|
|
385
|
+
step_status = DBOS.step_status
|
|
386
|
+
assert step_status is not None
|
|
387
|
+
assert step_status.step_id == 1
|
|
388
|
+
assert step_status.current_attempt == step_counter
|
|
389
|
+
assert step_status.max_attempts == max_attempts
|
|
388
390
|
step_counter += 1
|
|
389
391
|
if step_counter < max_attempts:
|
|
390
392
|
raise Exception("fail")
|
|
@@ -442,7 +444,9 @@ def test_keyboardinterrupt_during_retries(dbos: DBOS) -> None:
|
|
|
442
444
|
@DBOS.workflow()
|
|
443
445
|
def failing_workflow() -> str:
|
|
444
446
|
failing_step()
|
|
445
|
-
|
|
447
|
+
workflow_id = DBOS.workflow_id
|
|
448
|
+
assert workflow_id is not None
|
|
449
|
+
return workflow_id
|
|
446
450
|
|
|
447
451
|
with pytest.raises(KeyboardInterrupt):
|
|
448
452
|
failing_workflow()
|
|
@@ -112,7 +112,9 @@ def test_endpoint_recovery(dbos_fastapi: Tuple[DBOS, FastAPI]) -> None:
|
|
|
112
112
|
|
|
113
113
|
@DBOS.workflow()
|
|
114
114
|
def test_workflow(var1: str) -> tuple[str, str]:
|
|
115
|
-
|
|
115
|
+
workflow_id = DBOS.workflow_id
|
|
116
|
+
assert workflow_id is not None
|
|
117
|
+
return var1, workflow_id
|
|
116
118
|
|
|
117
119
|
@app.get("/{var1}/{var2}")
|
|
118
120
|
def test_endpoint(var1: str, var2: str) -> dict[str, str]:
|
|
@@ -72,7 +72,9 @@ def test_endpoint_recovery(dbos_flask: Tuple[DBOS, Flask]) -> None:
|
|
|
72
72
|
|
|
73
73
|
@DBOS.workflow()
|
|
74
74
|
def test_workflow(var1: str) -> tuple[str, str]:
|
|
75
|
-
|
|
75
|
+
workflow_id = DBOS.workflow_id
|
|
76
|
+
assert workflow_id is not None
|
|
77
|
+
return var1, workflow_id
|
|
76
78
|
|
|
77
79
|
@app.route("/<var1>/<var2>")
|
|
78
80
|
def test_endpoint(var1: str, var2: str) -> dict[str, str]:
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import logging
|
|
3
2
|
import multiprocessing
|
|
4
3
|
import multiprocessing.synchronize
|
|
5
4
|
import os
|
|
@@ -27,7 +26,7 @@ from dbos import (
|
|
|
27
26
|
)
|
|
28
27
|
from dbos._context import assert_current_dbos_context
|
|
29
28
|
from dbos._dbos import WorkflowHandleAsync
|
|
30
|
-
from dbos._error import DBOSAwaitedWorkflowCancelledError
|
|
29
|
+
from dbos._error import DBOSAwaitedWorkflowCancelledError
|
|
31
30
|
from dbos._schemas.system_database import SystemSchema
|
|
32
31
|
from dbos._sys_db import WorkflowStatusString
|
|
33
32
|
from dbos._utils import GlobalParams
|
|
@@ -943,7 +942,7 @@ def test_timeout_queue(dbos: DBOS) -> None:
|
|
|
943
942
|
|
|
944
943
|
with SetWorkflowTimeout(1.0):
|
|
945
944
|
handle = DBOS.start_workflow(blocked_parent_workflow)
|
|
946
|
-
with pytest.raises(
|
|
945
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
947
946
|
handle.get_result()
|
|
948
947
|
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
949
948
|
DBOS.retrieve_workflow(child_id).get_result()
|
|
@@ -1343,7 +1342,9 @@ def test_worker_concurrency_across_versions(dbos: DBOS, client: DBOSClient) -> N
|
|
|
1343
1342
|
|
|
1344
1343
|
@DBOS.workflow()
|
|
1345
1344
|
def test_workflow() -> str:
|
|
1346
|
-
|
|
1345
|
+
workflow_id = DBOS.workflow_id
|
|
1346
|
+
assert workflow_id is not None
|
|
1347
|
+
return workflow_id
|
|
1347
1348
|
|
|
1348
1349
|
# First enqueue a workflow on the other version, then on the current version
|
|
1349
1350
|
other_version = "other_version"
|
|
@@ -1417,7 +1418,9 @@ def test_unsetting_timeout(dbos: DBOS) -> None:
|
|
|
1417
1418
|
def child() -> str:
|
|
1418
1419
|
for _ in range(5):
|
|
1419
1420
|
DBOS.sleep(1)
|
|
1420
|
-
|
|
1421
|
+
workflow_id = DBOS.workflow_id
|
|
1422
|
+
assert workflow_id is not None
|
|
1423
|
+
return workflow_id
|
|
1421
1424
|
|
|
1422
1425
|
@DBOS.workflow()
|
|
1423
1426
|
def parent(child_one: str, child_two: str) -> None:
|
|
@@ -1448,7 +1451,9 @@ def test_queue_executor_id(dbos: DBOS) -> None:
|
|
|
1448
1451
|
|
|
1449
1452
|
@DBOS.workflow()
|
|
1450
1453
|
def example_workflow() -> str:
|
|
1451
|
-
|
|
1454
|
+
workflow_id = DBOS.workflow_id
|
|
1455
|
+
assert workflow_id is not None
|
|
1456
|
+
return workflow_id
|
|
1452
1457
|
|
|
1453
1458
|
# Set an executor ID
|
|
1454
1459
|
original_executor_id = str(uuid.uuid4())
|
|
@@ -195,7 +195,9 @@ def test_scheduler_oaoo(dbos: DBOS) -> None:
|
|
|
195
195
|
nonlocal wf_counter
|
|
196
196
|
wf_counter += 1
|
|
197
197
|
nonlocal workflow_id
|
|
198
|
-
|
|
198
|
+
wf_id = DBOS.workflow_id
|
|
199
|
+
assert wf_id is not None
|
|
200
|
+
workflow_id = wf_id
|
|
199
201
|
|
|
200
202
|
@DBOS.transaction()
|
|
201
203
|
def test_transaction() -> None:
|
|
@@ -456,7 +456,9 @@ def test_set_get_event(dbos: DBOS) -> None:
|
|
|
456
456
|
DBOS.set_event("key", value)
|
|
457
457
|
stepOne()
|
|
458
458
|
DBOS.get_event("fake_id", "fake_value", 0)
|
|
459
|
-
|
|
459
|
+
workflow_id = DBOS.workflow_id
|
|
460
|
+
assert workflow_id is not None
|
|
461
|
+
return DBOS.get_event(workflow_id, "key", 1)
|
|
460
462
|
|
|
461
463
|
@DBOS.step()
|
|
462
464
|
def stepOne() -> None:
|
|
@@ -500,7 +502,9 @@ def test_callchild_first_sync(dbos: DBOS) -> None:
|
|
|
500
502
|
|
|
501
503
|
@DBOS.workflow()
|
|
502
504
|
def child_workflow() -> str:
|
|
503
|
-
|
|
505
|
+
workflow_id = DBOS.workflow_id
|
|
506
|
+
assert workflow_id is not None
|
|
507
|
+
return workflow_id
|
|
504
508
|
|
|
505
509
|
wfid = str(uuid.uuid4())
|
|
506
510
|
with SetWorkflowID(wfid):
|
|
@@ -540,7 +544,9 @@ async def test_callchild_direct_asyncio(dbos: DBOS) -> None:
|
|
|
540
544
|
|
|
541
545
|
@DBOS.workflow()
|
|
542
546
|
async def child_workflow() -> str:
|
|
543
|
-
|
|
547
|
+
workflow_id = DBOS.workflow_id
|
|
548
|
+
assert workflow_id is not None
|
|
549
|
+
return workflow_id
|
|
544
550
|
|
|
545
551
|
wfid = str(uuid.uuid4())
|
|
546
552
|
with SetWorkflowID(wfid):
|
|
@@ -773,7 +779,9 @@ def test_callchild_middle_async_thread(dbos: DBOS) -> None:
|
|
|
773
779
|
|
|
774
780
|
@DBOS.step()
|
|
775
781
|
def stepOne() -> str:
|
|
776
|
-
|
|
782
|
+
workflow_id = DBOS.workflow_id
|
|
783
|
+
assert workflow_id is not None
|
|
784
|
+
return workflow_id
|
|
777
785
|
|
|
778
786
|
@DBOS.step()
|
|
779
787
|
def stepTwo() -> None:
|
|
@@ -781,7 +789,9 @@ def test_callchild_middle_async_thread(dbos: DBOS) -> None:
|
|
|
781
789
|
|
|
782
790
|
@DBOS.workflow()
|
|
783
791
|
def child_workflow() -> str:
|
|
784
|
-
|
|
792
|
+
workflow_id = DBOS.workflow_id
|
|
793
|
+
assert workflow_id is not None
|
|
794
|
+
return workflow_id
|
|
785
795
|
|
|
786
796
|
wfid = str(uuid.uuid4())
|
|
787
797
|
with SetWorkflowID(wfid):
|
|
@@ -821,7 +831,9 @@ async def test_callchild_first_asyncio(dbos: DBOS) -> None:
|
|
|
821
831
|
|
|
822
832
|
@DBOS.step()
|
|
823
833
|
def stepOne() -> str:
|
|
824
|
-
|
|
834
|
+
workflow_id = DBOS.workflow_id
|
|
835
|
+
assert workflow_id is not None
|
|
836
|
+
return workflow_id
|
|
825
837
|
|
|
826
838
|
@DBOS.step()
|
|
827
839
|
def stepTwo() -> None:
|
|
@@ -829,7 +841,9 @@ async def test_callchild_first_asyncio(dbos: DBOS) -> None:
|
|
|
829
841
|
|
|
830
842
|
@DBOS.workflow()
|
|
831
843
|
async def child_workflow() -> str:
|
|
832
|
-
|
|
844
|
+
workflow_id = DBOS.workflow_id
|
|
845
|
+
assert workflow_id is not None
|
|
846
|
+
return workflow_id
|
|
833
847
|
|
|
834
848
|
wfid = str(uuid.uuid4())
|
|
835
849
|
with SetWorkflowID(wfid):
|
|
@@ -1045,11 +1059,15 @@ def test_call_as_step_within_step(dbos: DBOS) -> None:
|
|
|
1045
1059
|
|
|
1046
1060
|
@DBOS.workflow()
|
|
1047
1061
|
def getStatusWorkflow() -> str:
|
|
1048
|
-
|
|
1062
|
+
workflow_id = DBOS.workflow_id
|
|
1063
|
+
assert workflow_id is not None
|
|
1064
|
+
return getStatus(workflow_id)
|
|
1049
1065
|
|
|
1050
1066
|
@DBOS.transaction()
|
|
1051
1067
|
def transactionStatus() -> None:
|
|
1052
|
-
DBOS.
|
|
1068
|
+
workflow_id = DBOS.workflow_id
|
|
1069
|
+
assert workflow_id is not None
|
|
1070
|
+
DBOS.get_workflow_status(workflow_id)
|
|
1053
1071
|
|
|
1054
1072
|
wfid = str(uuid.uuid4())
|
|
1055
1073
|
with SetWorkflowID(wfid):
|
|
@@ -9,7 +9,7 @@ import sqlalchemy as sa
|
|
|
9
9
|
# Public API
|
|
10
10
|
from dbos import DBOS, Queue, SetWorkflowID
|
|
11
11
|
from dbos._dbos import DBOSConfiguredInstance
|
|
12
|
-
from dbos._error import
|
|
12
|
+
from dbos._error import DBOSAwaitedWorkflowCancelledError
|
|
13
13
|
from dbos._schemas.application_database import ApplicationSchema
|
|
14
14
|
from dbos._utils import INTERNAL_QUEUE_NAME, GlobalParams
|
|
15
15
|
from dbos._workflow_commands import garbage_collect, global_timeout
|
|
@@ -52,7 +52,7 @@ def test_cancel_resume(dbos: DBOS) -> None:
|
|
|
52
52
|
main_thread_event.wait()
|
|
53
53
|
DBOS.cancel_workflow(wfid)
|
|
54
54
|
workflow_event.set()
|
|
55
|
-
with pytest.raises(
|
|
55
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
56
56
|
handle.get_result()
|
|
57
57
|
assert steps_completed == 1
|
|
58
58
|
|
|
@@ -103,7 +103,7 @@ def test_cancel_resume_txn(dbos: DBOS) -> None:
|
|
|
103
103
|
main_thread_event.wait()
|
|
104
104
|
DBOS.cancel_workflow(wfid)
|
|
105
105
|
workflow_event.set()
|
|
106
|
-
with pytest.raises(
|
|
106
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
107
107
|
handle.get_result()
|
|
108
108
|
assert txn_completed == 1
|
|
109
109
|
|
|
@@ -652,7 +652,9 @@ def test_garbage_collection(dbos: DBOS) -> None:
|
|
|
652
652
|
def blocked_workflow() -> str:
|
|
653
653
|
txn(0)
|
|
654
654
|
event.wait()
|
|
655
|
-
|
|
655
|
+
workflow_id = DBOS.workflow_id
|
|
656
|
+
assert workflow_id is not None
|
|
657
|
+
return workflow_id
|
|
656
658
|
|
|
657
659
|
num_workflows = 10
|
|
658
660
|
|
|
@@ -729,7 +731,9 @@ def test_global_timeout(dbos: DBOS) -> None:
|
|
|
729
731
|
def blocked_workflow() -> str:
|
|
730
732
|
while not event.wait(0):
|
|
731
733
|
DBOS.sleep(0.1)
|
|
732
|
-
|
|
734
|
+
workflow_id = DBOS.workflow_id
|
|
735
|
+
assert workflow_id is not None
|
|
736
|
+
return workflow_id
|
|
733
737
|
|
|
734
738
|
num_workflows = 10
|
|
735
739
|
handles = [DBOS.start_workflow(blocked_workflow) for _ in range(num_workflows)]
|
|
@@ -742,7 +746,7 @@ def test_global_timeout(dbos: DBOS) -> None:
|
|
|
742
746
|
|
|
743
747
|
# Verify all workflows started before the global timeout are cancelled
|
|
744
748
|
for handle in handles:
|
|
745
|
-
with pytest.raises(
|
|
749
|
+
with pytest.raises(DBOSAwaitedWorkflowCancelledError):
|
|
746
750
|
handle.get_result()
|
|
747
751
|
event.set()
|
|
748
752
|
assert final_handle.get_result() is not None
|
|
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
|
{dbos-1.8.0a8 → dbos-1.9.0}/dbos/_migrations/versions/04ca4f231047_workflow_queues_executor_id.py
RENAMED
|
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
|
|
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
|