dbos 2.4.0a2__tar.gz → 2.4.0a3__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 (99) hide show
  1. {dbos-2.4.0a2 → dbos-2.4.0a3}/PKG-INFO +1 -1
  2. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_admin_server.py +2 -0
  3. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_conductor/conductor.py +2 -0
  4. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_conductor/protocol.py +2 -2
  5. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_dbos.py +8 -0
  6. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_migration.py +2 -0
  7. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_sys_db.py +9 -28
  8. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_workflow_commands.py +4 -0
  9. {dbos-2.4.0a2 → dbos-2.4.0a3}/pyproject.toml +1 -1
  10. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_admin_server.py +8 -3
  11. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_workflow_management.py +3 -7
  12. {dbos-2.4.0a2 → dbos-2.4.0a3}/LICENSE +0 -0
  13. {dbos-2.4.0a2 → dbos-2.4.0a3}/README.md +0 -0
  14. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/__init__.py +0 -0
  15. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/__main__.py +0 -0
  16. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_app_db.py +0 -0
  17. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_classproperty.py +0 -0
  18. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_client.py +0 -0
  19. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_context.py +0 -0
  20. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_core.py +0 -0
  21. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_croniter.py +0 -0
  22. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_dbos_config.py +0 -0
  23. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_debouncer.py +0 -0
  24. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_debug.py +0 -0
  25. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_docker_pg_helper.py +0 -0
  26. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_error.py +0 -0
  27. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_event_loop.py +0 -0
  28. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_fastapi.py +0 -0
  29. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_flask.py +0 -0
  30. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_kafka.py +0 -0
  31. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_kafka_message.py +0 -0
  32. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_logger.py +0 -0
  33. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_outcome.py +0 -0
  34. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_queue.py +0 -0
  35. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_recovery.py +0 -0
  36. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_registrations.py +0 -0
  37. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_roles.py +0 -0
  38. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_scheduler.py +0 -0
  39. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_schemas/__init__.py +0 -0
  40. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_schemas/application_database.py +0 -0
  41. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_schemas/system_database.py +0 -0
  42. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_serialization.py +0 -0
  43. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_sys_db_postgres.py +0 -0
  44. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_sys_db_sqlite.py +0 -0
  45. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_templates/dbos-db-starter/README.md +0 -0
  46. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_templates/dbos-db-starter/__package/__init__.py +0 -0
  47. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_templates/dbos-db-starter/__package/main.py.dbos +0 -0
  48. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_templates/dbos-db-starter/__package/schema.py +0 -0
  49. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_templates/dbos-db-starter/dbos-config.yaml.dbos +0 -0
  50. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_templates/dbos-db-starter/migrations/create_table.py.dbos +0 -0
  51. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_templates/dbos-db-starter/start_postgres_docker.py +0 -0
  52. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_tracer.py +0 -0
  53. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/_utils.py +0 -0
  54. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/cli/_github_init.py +0 -0
  55. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/cli/_template_init.py +0 -0
  56. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/cli/cli.py +0 -0
  57. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/cli/migration.py +0 -0
  58. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/dbos-config.schema.json +0 -0
  59. {dbos-2.4.0a2 → dbos-2.4.0a3}/dbos/py.typed +0 -0
  60. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/__init__.py +0 -0
  61. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/atexit_no_ctor.py +0 -0
  62. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/atexit_no_launch.py +0 -0
  63. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/classdefs.py +0 -0
  64. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/client_collateral.py +0 -0
  65. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/client_worker.py +0 -0
  66. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/conftest.py +0 -0
  67. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/dupname_classdefs1.py +0 -0
  68. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/dupname_classdefsa.py +0 -0
  69. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/more_classdefs.py +0 -0
  70. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/queuedworkflow.py +0 -0
  71. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/script_without_fastapi.py +0 -0
  72. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_async.py +0 -0
  73. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_async_workflow_management.py +0 -0
  74. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_classdecorators.py +0 -0
  75. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_cli.py +0 -0
  76. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_client.py +0 -0
  77. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_concurrency.py +0 -0
  78. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_config.py +0 -0
  79. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_croniter.py +0 -0
  80. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_dbos.py +0 -0
  81. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_debouncer.py +0 -0
  82. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_debug.py +0 -0
  83. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_docker_secrets.py +0 -0
  84. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_failures.py +0 -0
  85. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_fastapi.py +0 -0
  86. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_fastapi_roles.py +0 -0
  87. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_flask.py +0 -0
  88. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_kafka.py +0 -0
  89. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_outcome.py +0 -0
  90. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_package.py +0 -0
  91. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_queue.py +0 -0
  92. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_scheduler.py +0 -0
  93. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_schema_migration.py +0 -0
  94. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_singleton.py +0 -0
  95. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_spans.py +0 -0
  96. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_sqlalchemy.py +0 -0
  97. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_streaming.py +0 -0
  98. {dbos-2.4.0a2 → dbos-2.4.0a3}/tests/test_workflow_introspection.py +0 -0
  99. {dbos-2.4.0a2 → dbos-2.4.0a3}/version/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 2.4.0a2
3
+ Version: 2.4.0a3
4
4
  Summary: Ultra-lightweight durable execution in Python
5
5
  Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
6
  License: MIT
@@ -338,6 +338,7 @@ class AdminRequestHandler(BaseHTTPRequestHandler):
338
338
  end_time=filters.get("end_time"),
339
339
  status=filters.get("status"),
340
340
  app_version=filters.get("application_version"),
341
+ forked_from=filters.get("forked_from"),
341
342
  name=filters.get("workflow_name"),
342
343
  limit=filters.get("limit"),
343
344
  offset=filters.get("offset"),
@@ -364,6 +365,7 @@ class AdminRequestHandler(BaseHTTPRequestHandler):
364
365
  start_time=filters.get("start_time"),
365
366
  end_time=filters.get("end_time"),
366
367
  status=filters.get("status"),
368
+ forked_from=filters.get("forked_from"),
367
369
  name=filters.get("workflow_name"),
368
370
  limit=filters.get("limit"),
369
371
  offset=filters.get("offset"),
@@ -233,6 +233,7 @@ class ConductorWebsocket(threading.Thread):
233
233
  end_time=body["end_time"],
234
234
  status=body["status"],
235
235
  app_version=body["application_version"],
236
+ forked_from=body["forked_from"],
236
237
  name=body["workflow_name"],
237
238
  limit=body["limit"],
238
239
  offset=body["offset"],
@@ -267,6 +268,7 @@ class ConductorWebsocket(threading.Thread):
267
268
  start_time=q_body["start_time"],
268
269
  end_time=q_body["end_time"],
269
270
  status=q_body["status"],
271
+ forked_from=q_body["forked_from"],
270
272
  name=q_body["workflow_name"],
271
273
  limit=q_body["limit"],
272
274
  offset=q_body["offset"],
@@ -118,6 +118,7 @@ class ListWorkflowsBody(TypedDict, total=False):
118
118
  end_time: Optional[str]
119
119
  status: Optional[str]
120
120
  application_version: Optional[str]
121
+ forked_from: Optional[str]
121
122
  limit: Optional[int]
122
123
  offset: Optional[int]
123
124
  sort_desc: bool
@@ -149,7 +150,6 @@ class WorkflowsOutput:
149
150
  Priority: Optional[str]
150
151
  QueuePartitionKey: Optional[str]
151
152
  ForkedFrom: Optional[str]
152
- ForkedTo: Optional[list[str]]
153
153
 
154
154
  @classmethod
155
155
  def from_workflow_information(cls, info: WorkflowStatus) -> "WorkflowsOutput":
@@ -199,7 +199,6 @@ class WorkflowsOutput:
199
199
  Priority=priority_str,
200
200
  QueuePartitionKey=info.queue_partition_key,
201
201
  ForkedFrom=info.forked_from,
202
- ForkedTo=info.forked_to,
203
202
  )
204
203
 
205
204
 
@@ -254,6 +253,7 @@ class ListQueuedWorkflowsBody(TypedDict, total=False):
254
253
  start_time: Optional[str]
255
254
  end_time: Optional[str]
256
255
  status: Optional[str]
256
+ forked_from: Optional[str]
257
257
  queue_name: Optional[str]
258
258
  limit: Optional[int]
259
259
  offset: Optional[int]
@@ -1127,6 +1127,7 @@ class DBOS:
1127
1127
  end_time: Optional[str] = None,
1128
1128
  name: Optional[str] = None,
1129
1129
  app_version: Optional[str] = None,
1130
+ forked_from: Optional[str] = None,
1130
1131
  user: Optional[str] = None,
1131
1132
  queue_name: Optional[str] = None,
1132
1133
  limit: Optional[int] = None,
@@ -1145,6 +1146,7 @@ class DBOS:
1145
1146
  end_time=end_time,
1146
1147
  name=name,
1147
1148
  app_version=app_version,
1149
+ forked_from=forked_from,
1148
1150
  user=user,
1149
1151
  limit=limit,
1150
1152
  offset=offset,
@@ -1169,6 +1171,7 @@ class DBOS:
1169
1171
  end_time: Optional[str] = None,
1170
1172
  name: Optional[str] = None,
1171
1173
  app_version: Optional[str] = None,
1174
+ forked_from: Optional[str] = None,
1172
1175
  user: Optional[str] = None,
1173
1176
  limit: Optional[int] = None,
1174
1177
  offset: Optional[int] = None,
@@ -1186,6 +1189,7 @@ class DBOS:
1186
1189
  end_time=end_time,
1187
1190
  name=name,
1188
1191
  app_version=app_version,
1192
+ forked_from=forked_from,
1189
1193
  user=user,
1190
1194
  limit=limit,
1191
1195
  offset=offset,
@@ -1201,6 +1205,7 @@ class DBOS:
1201
1205
  *,
1202
1206
  queue_name: Optional[str] = None,
1203
1207
  status: Optional[Union[str, List[str]]] = None,
1208
+ forked_from: Optional[str] = None,
1204
1209
  start_time: Optional[str] = None,
1205
1210
  end_time: Optional[str] = None,
1206
1211
  name: Optional[str] = None,
@@ -1214,6 +1219,7 @@ class DBOS:
1214
1219
  _get_dbos_instance()._sys_db,
1215
1220
  queue_name=queue_name,
1216
1221
  status=status,
1222
+ forked_from=forked_from,
1217
1223
  start_time=start_time,
1218
1224
  end_time=end_time,
1219
1225
  name=name,
@@ -1233,6 +1239,7 @@ class DBOS:
1233
1239
  *,
1234
1240
  queue_name: Optional[str] = None,
1235
1241
  status: Optional[Union[str, List[str]]] = None,
1242
+ forked_from: Optional[str] = None,
1236
1243
  start_time: Optional[str] = None,
1237
1244
  end_time: Optional[str] = None,
1238
1245
  name: Optional[str] = None,
@@ -1246,6 +1253,7 @@ class DBOS:
1246
1253
  cls.list_queued_workflows,
1247
1254
  queue_name=queue_name,
1248
1255
  status=status,
1256
+ forked_from=forked_from,
1249
1257
  start_time=start_time,
1250
1258
  end_time=end_time,
1251
1259
  name=name,
@@ -218,6 +218,7 @@ create index "idx_workflow_status_queue_status_started" on \"{schema}\"."workflo
218
218
  def get_dbos_migration_four(schema: str) -> str:
219
219
  return f"""
220
220
  ALTER TABLE \"{schema}\".workflow_status ADD COLUMN forked_from TEXT;
221
+ CREATE INDEX "idx_workflow_status_forked_from" ON \"{schema}\"."workflow_status" ("forked_from")
221
222
  """
222
223
 
223
224
 
@@ -334,6 +335,7 @@ ON "workflow_status" ("queue_name", "status", "started_at_epoch_ms")
334
335
 
335
336
  sqlite_migration_four = """
336
337
  ALTER TABLE workflow_status ADD COLUMN forked_from TEXT;
338
+ CREATE INDEX "idx_workflow_status_forked_from" ON "workflow_status" ("forked_from")
337
339
  """
338
340
 
339
341
  sqlite_migration_five = """
@@ -106,7 +106,7 @@ class WorkflowStatus:
106
106
  updated_at: Optional[int]
107
107
  # If this workflow was enqueued, on which queue
108
108
  queue_name: Optional[str]
109
- # The executor to most recently executed this workflow
109
+ # The executor to most recently execute this workflow
110
110
  executor_id: Optional[str]
111
111
  # The application version on which this workflow was started
112
112
  app_version: Optional[str]
@@ -122,8 +122,6 @@ class WorkflowStatus:
122
122
  queue_partition_key: Optional[str]
123
123
  # If this workflow was forked from another, that workflow's ID.
124
124
  forked_from: Optional[str]
125
- # If this workflow was forked to others, those workflows' IDs
126
- forked_to: Optional[list[str]]
127
125
 
128
126
  # INTERNAL FIELDS
129
127
 
@@ -213,6 +211,8 @@ class GetWorkflowsInput:
213
211
  self.status: Optional[List[str]] = None
214
212
  # The application version that ran this workflow.
215
213
  self.application_version: Optional[str] = None
214
+ # Get workflows forked from this workflow ID.
215
+ self.forked_from: Optional[str] = None
216
216
  # Return up to this many workflows IDs. IDs are ordered by workflow creation time.
217
217
  self.limit: Optional[int] = None
218
218
  # Offset into the matching records for pagination
@@ -244,9 +244,9 @@ class StepInfo(TypedDict):
244
244
  error: Optional[Exception]
245
245
  # If the step starts or retrieves the result of a workflow, its ID
246
246
  child_workflow_id: Optional[str]
247
- # The UNIX epoch timestamp at which this step started
247
+ # The Unix epoch timestamp at which this step started
248
248
  started_at_epoch_ms: Optional[int]
249
- # The UNIX epoch timestamp at which this step completed
249
+ # The Unix epoch timestamp at which this step completed
250
250
  completed_at_epoch_ms: Optional[int]
251
251
 
252
252
 
@@ -931,6 +931,10 @@ class SystemDatabase(ABC):
931
931
  SystemSchema.workflow_status.c.application_version
932
932
  == input.application_version
933
933
  )
934
+ if input.forked_from:
935
+ query = query.where(
936
+ SystemSchema.workflow_status.c.forked_from == input.forked_from
937
+ )
934
938
  if input.workflow_ids:
935
939
  query = query.where(
936
940
  SystemSchema.workflow_status.c.workflow_uuid.in_(input.workflow_ids)
@@ -997,29 +1001,6 @@ class SystemDatabase(ABC):
997
1001
 
998
1002
  workflow_ids.append(info.workflow_id)
999
1003
  infos.append(info)
1000
-
1001
- # Calculate forked_to relationships
1002
- if workflow_ids:
1003
- with self.engine.begin() as c:
1004
- forked_to_query = sa.select(
1005
- SystemSchema.workflow_status.c.forked_from,
1006
- SystemSchema.workflow_status.c.workflow_uuid,
1007
- ).where(SystemSchema.workflow_status.c.forked_from.in_(workflow_ids))
1008
- forked_to_rows = c.execute(forked_to_query).fetchall()
1009
-
1010
- # Build a mapping of fork-parent workflow ID to list of fork-child workflow IDs
1011
- forked_to_map: Dict[str, List[str]] = {}
1012
- for row in forked_to_rows:
1013
- parent_id = row[0]
1014
- child_id = row[1]
1015
- if parent_id not in forked_to_map:
1016
- forked_to_map[parent_id] = []
1017
- forked_to_map[parent_id].append(child_id)
1018
-
1019
- # Populate the forked_to field for each workflow
1020
- for info in infos:
1021
- info.forked_to = forked_to_map.get(info.workflow_id, None)
1022
-
1023
1004
  return infos
1024
1005
 
1025
1006
  def get_pending_workflows(
@@ -26,6 +26,7 @@ def list_workflows(
26
26
  end_time: Optional[str] = None,
27
27
  name: Optional[str] = None,
28
28
  app_version: Optional[str] = None,
29
+ forked_from: Optional[str] = None,
29
30
  user: Optional[str] = None,
30
31
  queue_name: Optional[str] = None,
31
32
  limit: Optional[int] = None,
@@ -42,6 +43,7 @@ def list_workflows(
42
43
  input.end_time = end_time
43
44
  input.status = status if status is None or isinstance(status, list) else [status]
44
45
  input.application_version = app_version
46
+ input.forked_from = forked_from
45
47
  input.queue_name = queue_name
46
48
  input.limit = limit
47
49
  input.name = name
@@ -61,6 +63,7 @@ def list_queued_workflows(
61
63
  *,
62
64
  queue_name: Optional[str] = None,
63
65
  status: Optional[Union[str, List[str]]] = None,
66
+ forked_from: Optional[str] = None,
64
67
  start_time: Optional[str] = None,
65
68
  end_time: Optional[str] = None,
66
69
  name: Optional[str] = None,
@@ -73,6 +76,7 @@ def list_queued_workflows(
73
76
  input.start_time = start_time
74
77
  input.end_time = end_time
75
78
  input.status = status if status is None or isinstance(status, list) else [status]
79
+ input.forked_from = forked_from
76
80
  input.limit = limit
77
81
  input.name = name
78
82
  input.offset = offset
@@ -34,7 +34,7 @@ classifiers = [
34
34
  "Topic :: Software Development :: Libraries :: Python Modules",
35
35
  "Framework :: AsyncIO",
36
36
  ]
37
- version = "2.4.0a2"
37
+ version = "2.4.0a3"
38
38
 
39
39
  [project.license]
40
40
  text = "MIT"
@@ -527,7 +527,6 @@ def test_list_workflows(dbos: DBOS, skip_with_sqlite_imprecise_time: None) -> No
527
527
  assert workflows[0]["Priority"] == "0"
528
528
  assert workflows[0]["QueuePartitionKey"] is None
529
529
  assert workflows[0]["ForkedFrom"] is None
530
- assert workflows[0]["ForkedTo"] is None
531
530
 
532
531
  # Only load input and output as requested
533
532
  filters = {
@@ -600,10 +599,8 @@ def test_list_workflows(dbos: DBOS, skip_with_sqlite_imprecise_time: None) -> No
600
599
  assert len(workflows) == 2
601
600
  assert workflows[0]["WorkflowUUID"] == handle_1.workflow_id
602
601
  assert workflows[0]["ForkedFrom"] == None
603
- assert workflows[0]["ForkedTo"] == [handle_3.workflow_id]
604
602
  assert workflows[1]["WorkflowUUID"] == handle_3.workflow_id
605
603
  assert workflows[1]["ForkedFrom"] == handle_1.workflow_id
606
- assert workflows[1]["ForkedTo"] == None
607
604
 
608
605
  filters = {
609
606
  "end_time": (datetime.now(timezone.utc) - timedelta(minutes=10)).isoformat()
@@ -621,6 +618,14 @@ def test_list_workflows(dbos: DBOS, skip_with_sqlite_imprecise_time: None) -> No
621
618
  workflows = response.json()
622
619
  assert len(workflows) == 0
623
620
 
621
+ filters = {
622
+ "forked_from": "not-an-id",
623
+ }
624
+ response = requests.post("http://localhost:3001/workflows", json=filters, timeout=5)
625
+ assert response.status_code == 200
626
+ workflows = response.json()
627
+ assert len(workflows) == 0
628
+
624
629
  filters = {
625
630
  "status": ["SUCCESS", "CANCELLED"],
626
631
  }
@@ -262,8 +262,9 @@ def test_fork_steps(
262
262
  assert stepFourCount == 3
263
263
  assert stepFiveCount == 4
264
264
 
265
- handle: WorkflowHandle[int] = DBOS.retrieve_workflow(wfid)
266
- assert handle.get_status().forked_to == [fork_id, fork_id_2, fork_id_3]
265
+ forks = DBOS.list_workflows(forked_from=wfid)
266
+ assert len(forks) == 3
267
+ assert [f.workflow_id for f in forks] == [fork_id, fork_id_2, fork_id_3]
267
268
 
268
269
 
269
270
  def test_restart_fromsteps_transactionsonly(
@@ -357,11 +358,6 @@ def test_restart_fromsteps_transactionsonly(
357
358
  assert trThreeCount == 3
358
359
  assert trFourCount == 4
359
360
  assert trFiveCount == 4
360
- assert DBOS.retrieve_workflow(wfid).get_status().forked_to == [
361
- fork_id_one,
362
- fork_id_two,
363
- fork_id_three,
364
- ]
365
361
 
366
362
 
367
363
  def test_restart_fromsteps_steps_tr(
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