dbos 0.26.0a5__tar.gz → 0.26.0a7__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.
- {dbos-0.26.0a5 → dbos-0.26.0a7}/PKG-INFO +1 -1
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_app_db.py +61 -2
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_conductor/conductor.py +1 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_core.py +4 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_dbos.py +6 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_schemas/application_database.py +1 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_workflow_commands.py +9 -3
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/cli/cli.py +4 -1
- {dbos-0.26.0a5 → dbos-0.26.0a7}/pyproject.toml +1 -1
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/conftest.py +8 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_dbos.py +57 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_workflow_introspection.py +137 -37
- {dbos-0.26.0a5 → dbos-0.26.0a7}/LICENSE +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/README.md +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/__init__.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/__main__.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_admin_server.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_classproperty.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_client.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_cloudutils/authentication.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_cloudutils/cloudutils.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_cloudutils/databases.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_conductor/protocol.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_context.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_croniter.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_db_wizard.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_dbos_config.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_debug.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_error.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_fastapi.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_flask.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_kafka.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_kafka_message.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_logger.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/env.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/script.py.mako +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/04ca4f231047_workflow_queues_executor_id.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/50f3227f0b4b_fix_job_queue.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/5c361fc04708_added_system_tables.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/a3b18ad34abe_added_triggers.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/d76646551a6b_job_queue_limiter.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/d76646551a6c_workflow_queue.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/eab0cc1d9a14_job_queue.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/f4b9b32ba814_functionname_childid_op_outputs.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_outcome.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_queue.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_recovery.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_registrations.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_request.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_roles.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_scheduler.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_schemas/__init__.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_schemas/system_database.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_serialization.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_sys_db.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/README.md +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/__package/__init__.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/__package/main.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/__package/schema.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/alembic.ini +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/dbos-config.yaml.dbos +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/migrations/env.py.dbos +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/migrations/script.py.mako +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/migrations/versions/2024_07_31_180642_init.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_templates/dbos-db-starter/start_postgres_docker.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_tracer.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_utils.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/cli/_github_init.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/cli/_template_init.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/dbos-config.schema.json +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/py.typed +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/__init__.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/atexit_no_ctor.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/atexit_no_launch.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/classdefs.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/client_collateral.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/client_worker.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/more_classdefs.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/queuedworkflow.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_admin_server.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_async.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_classdecorators.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_client.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_concurrency.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_config.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_croniter.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_dbwizard.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_debug.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_docker_secrets.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_failures.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_fastapi.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_fastapi_roles.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_flask.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_kafka.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_outcome.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_package.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_queue.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_scheduler.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_schema_migration.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_singleton.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_spans.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_sqlalchemy.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/tests/test_workflow_management.py +0 -0
- {dbos-0.26.0a5 → dbos-0.26.0a7}/version/__init__.py +0 -0
@@ -1,13 +1,16 @@
|
|
1
|
-
from typing import Optional, TypedDict
|
1
|
+
from typing import List, Optional, TypedDict
|
2
2
|
|
3
3
|
import sqlalchemy as sa
|
4
4
|
import sqlalchemy.dialects.postgresql as pg
|
5
|
+
from sqlalchemy import inspect, text
|
5
6
|
from sqlalchemy.exc import DBAPIError
|
6
7
|
from sqlalchemy.orm import Session, sessionmaker
|
7
8
|
|
9
|
+
from . import _serialization
|
8
10
|
from ._dbos_config import ConfigFile, DatabaseConfig
|
9
11
|
from ._error import DBOSWorkflowConflictIDError
|
10
12
|
from ._schemas.application_database import ApplicationSchema
|
13
|
+
from ._sys_db import StepInfo
|
11
14
|
|
12
15
|
|
13
16
|
class TransactionResultInternal(TypedDict):
|
@@ -18,6 +21,7 @@ class TransactionResultInternal(TypedDict):
|
|
18
21
|
txn_id: Optional[str]
|
19
22
|
txn_snapshot: str
|
20
23
|
executor_id: Optional[str]
|
24
|
+
function_name: Optional[str]
|
21
25
|
|
22
26
|
|
23
27
|
class RecordedResult(TypedDict):
|
@@ -87,7 +91,30 @@ class ApplicationDatabase:
|
|
87
91
|
f"CREATE SCHEMA IF NOT EXISTS {ApplicationSchema.schema}"
|
88
92
|
)
|
89
93
|
conn.execute(schema_creation_query)
|
90
|
-
|
94
|
+
|
95
|
+
inspector = inspect(self.engine)
|
96
|
+
if not inspector.has_table(
|
97
|
+
"transaction_outputs", schema=ApplicationSchema.schema
|
98
|
+
):
|
99
|
+
ApplicationSchema.metadata_obj.create_all(self.engine)
|
100
|
+
else:
|
101
|
+
columns = inspector.get_columns(
|
102
|
+
"transaction_outputs", schema=ApplicationSchema.schema
|
103
|
+
)
|
104
|
+
column_names = [col["name"] for col in columns]
|
105
|
+
|
106
|
+
if "function_name" not in column_names:
|
107
|
+
# Column missing, alter table to add it
|
108
|
+
with self.engine.connect() as conn:
|
109
|
+
conn.execute(
|
110
|
+
text(
|
111
|
+
f"""
|
112
|
+
ALTER TABLE {ApplicationSchema.schema}.transaction_outputs
|
113
|
+
ADD COLUMN function_name TEXT NOT NULL DEFAULT '';
|
114
|
+
"""
|
115
|
+
)
|
116
|
+
)
|
117
|
+
conn.commit()
|
91
118
|
|
92
119
|
def destroy(self) -> None:
|
93
120
|
self.engine.dispose()
|
@@ -108,6 +135,7 @@ class ApplicationDatabase:
|
|
108
135
|
executor_id=(
|
109
136
|
output["executor_id"] if output["executor_id"] else None
|
110
137
|
),
|
138
|
+
function_name=output["function_name"],
|
111
139
|
)
|
112
140
|
)
|
113
141
|
except DBAPIError as dbapi_error:
|
@@ -133,6 +161,7 @@ class ApplicationDatabase:
|
|
133
161
|
executor_id=(
|
134
162
|
output["executor_id"] if output["executor_id"] else None
|
135
163
|
),
|
164
|
+
function_name=output["function_name"],
|
136
165
|
)
|
137
166
|
)
|
138
167
|
except DBAPIError as dbapi_error:
|
@@ -160,3 +189,33 @@ class ApplicationDatabase:
|
|
160
189
|
"error": rows[0][1],
|
161
190
|
}
|
162
191
|
return result
|
192
|
+
|
193
|
+
def get_transactions(self, workflow_uuid: str) -> List[StepInfo]:
|
194
|
+
with self.engine.begin() as conn:
|
195
|
+
rows = conn.execute(
|
196
|
+
sa.select(
|
197
|
+
ApplicationSchema.transaction_outputs.c.function_id,
|
198
|
+
ApplicationSchema.transaction_outputs.c.function_name,
|
199
|
+
ApplicationSchema.transaction_outputs.c.output,
|
200
|
+
ApplicationSchema.transaction_outputs.c.error,
|
201
|
+
).where(
|
202
|
+
ApplicationSchema.transaction_outputs.c.workflow_uuid
|
203
|
+
== workflow_uuid,
|
204
|
+
)
|
205
|
+
).all()
|
206
|
+
return [
|
207
|
+
StepInfo(
|
208
|
+
function_id=row[0],
|
209
|
+
function_name=row[1],
|
210
|
+
output=(
|
211
|
+
_serialization.deserialize(row[2]) if row[2] is not None else row[2]
|
212
|
+
),
|
213
|
+
error=(
|
214
|
+
_serialization.deserialize_exception(row[3])
|
215
|
+
if row[3] is not None
|
216
|
+
else row[3]
|
217
|
+
),
|
218
|
+
child_workflow_id=None,
|
219
|
+
)
|
220
|
+
for row in rows
|
221
|
+
]
|
@@ -782,6 +782,9 @@ def decorate_transaction(
|
|
782
782
|
dbosreg: "DBOSRegistry", isolation_level: "IsolationLevel" = "SERIALIZABLE"
|
783
783
|
) -> Callable[[F], F]:
|
784
784
|
def decorator(func: F) -> F:
|
785
|
+
|
786
|
+
transactionName = func.__qualname__
|
787
|
+
|
785
788
|
def invoke_tx(*args: Any, **kwargs: Any) -> Any:
|
786
789
|
if dbosreg.dbos is None:
|
787
790
|
raise DBOSException(
|
@@ -810,6 +813,7 @@ def decorate_transaction(
|
|
810
813
|
"txn_snapshot": "", # TODO: add actual snapshot
|
811
814
|
"executor_id": None,
|
812
815
|
"txn_id": None,
|
816
|
+
"function_name": transactionName,
|
813
817
|
}
|
814
818
|
retry_wait_seconds = 0.001
|
815
819
|
backoff_factor = 1.5
|
@@ -172,6 +172,12 @@ class DBOSRegistry:
|
|
172
172
|
if name in self.function_type_map:
|
173
173
|
if self.function_type_map[name] != functype:
|
174
174
|
raise DBOSConflictingRegistrationError(name)
|
175
|
+
if name != TEMP_SEND_WF_NAME:
|
176
|
+
# Remove the `<temp>` prefix from the function name to avoid confusion
|
177
|
+
truncated_name = name.replace("<temp>.", "")
|
178
|
+
dbos_logger.warning(
|
179
|
+
f"Duplicate registration of function '{truncated_name}'. A function named '{truncated_name}' has already been registered with DBOS. All functions registered with DBOS must have unique names."
|
180
|
+
)
|
175
181
|
self.function_type_map[name] = functype
|
176
182
|
self.workflow_info_map[name] = wrapped_func
|
177
183
|
|
@@ -2,6 +2,7 @@ import json
|
|
2
2
|
from typing import Any, List, Optional
|
3
3
|
|
4
4
|
from . import _serialization
|
5
|
+
from ._app_db import ApplicationDatabase
|
5
6
|
from ._sys_db import (
|
6
7
|
GetQueuedWorkflowsInput,
|
7
8
|
GetWorkflowsInput,
|
@@ -170,6 +171,11 @@ def get_workflow(
|
|
170
171
|
return info
|
171
172
|
|
172
173
|
|
173
|
-
def list_workflow_steps(
|
174
|
-
|
175
|
-
|
174
|
+
def list_workflow_steps(
|
175
|
+
sys_db: SystemDatabase, app_db: ApplicationDatabase, workflow_id: str
|
176
|
+
) -> List[StepInfo]:
|
177
|
+
steps = sys_db.get_workflow_steps(workflow_id)
|
178
|
+
transactions = app_db.get_transactions(workflow_id)
|
179
|
+
merged_steps = steps + transactions
|
180
|
+
merged_steps.sort(key=lambda step: step["function_id"])
|
181
|
+
return merged_steps
|
@@ -350,8 +350,11 @@ def steps(
|
|
350
350
|
) -> None:
|
351
351
|
config = load_config(silent=True)
|
352
352
|
sys_db = SystemDatabase(config["database"])
|
353
|
+
app_db = ApplicationDatabase(config["database"])
|
353
354
|
print(
|
354
|
-
jsonpickle.encode(
|
355
|
+
jsonpickle.encode(
|
356
|
+
list_workflow_steps(sys_db, app_db, workflow_id), unpicklable=False
|
357
|
+
)
|
355
358
|
)
|
356
359
|
|
357
360
|
|
@@ -11,6 +11,7 @@ from fastapi import FastAPI
|
|
11
11
|
from flask import Flask
|
12
12
|
|
13
13
|
from dbos import DBOS, ConfigFile, DBOSClient
|
14
|
+
from dbos._app_db import ApplicationDatabase
|
14
15
|
from dbos._schemas.system_database import SystemSchema
|
15
16
|
from dbos._sys_db import SystemDatabase
|
16
17
|
|
@@ -48,6 +49,13 @@ def sys_db(config: ConfigFile) -> Generator[SystemDatabase, Any, None]:
|
|
48
49
|
sys_db.destroy()
|
49
50
|
|
50
51
|
|
52
|
+
@pytest.fixture()
|
53
|
+
def app_db(config: ConfigFile) -> Generator[ApplicationDatabase, Any, None]:
|
54
|
+
app_db = ApplicationDatabase(config["database"])
|
55
|
+
yield app_db
|
56
|
+
app_db.destroy()
|
57
|
+
|
58
|
+
|
51
59
|
@pytest.fixture(scope="session")
|
52
60
|
def postgres_db_engine() -> sa.Engine:
|
53
61
|
cfg = default_config()
|
@@ -1257,6 +1257,63 @@ def test_double_decoration(dbos: DBOS) -> None:
|
|
1257
1257
|
my_function()
|
1258
1258
|
|
1259
1259
|
|
1260
|
+
def test_duplicate_registration(
|
1261
|
+
dbos: DBOS, caplog: pytest.LogCaptureFixture, config: ConfigFile
|
1262
|
+
) -> None:
|
1263
|
+
original_propagate = logging.getLogger("dbos").propagate
|
1264
|
+
caplog.set_level(logging.WARNING, "dbos")
|
1265
|
+
logging.getLogger("dbos").propagate = True
|
1266
|
+
|
1267
|
+
@DBOS.transaction()
|
1268
|
+
def my_transaction() -> None:
|
1269
|
+
pass
|
1270
|
+
|
1271
|
+
@DBOS.transaction()
|
1272
|
+
def my_transaction() -> None:
|
1273
|
+
pass
|
1274
|
+
|
1275
|
+
assert (
|
1276
|
+
"Duplicate registration of function 'test_duplicate_registration.<locals>.my_transaction'"
|
1277
|
+
in caplog.text
|
1278
|
+
)
|
1279
|
+
|
1280
|
+
@DBOS.step()
|
1281
|
+
def my_step() -> None:
|
1282
|
+
pass
|
1283
|
+
|
1284
|
+
@DBOS.step()
|
1285
|
+
def my_step() -> None:
|
1286
|
+
pass
|
1287
|
+
|
1288
|
+
assert (
|
1289
|
+
"Duplicate registration of function 'test_duplicate_registration.<locals>.my_step'"
|
1290
|
+
in caplog.text
|
1291
|
+
)
|
1292
|
+
|
1293
|
+
@DBOS.workflow()
|
1294
|
+
def my_workflow() -> None:
|
1295
|
+
my_step()
|
1296
|
+
my_transaction()
|
1297
|
+
|
1298
|
+
@DBOS.workflow()
|
1299
|
+
def my_workflow() -> None:
|
1300
|
+
my_step()
|
1301
|
+
my_transaction()
|
1302
|
+
|
1303
|
+
assert (
|
1304
|
+
"Duplicate registration of function 'test_duplicate_registration.<locals>.my_workflow'"
|
1305
|
+
in caplog.text
|
1306
|
+
)
|
1307
|
+
|
1308
|
+
DBOS.destroy()
|
1309
|
+
DBOS(config=config)
|
1310
|
+
DBOS.launch()
|
1311
|
+
assert "Duplicate registration of function 'temp_send_workflow'" not in caplog.text
|
1312
|
+
|
1313
|
+
# Reset logging
|
1314
|
+
logging.getLogger("dbos").propagate = original_propagate
|
1315
|
+
|
1316
|
+
|
1260
1317
|
def test_app_version(config: ConfigFile) -> None:
|
1261
1318
|
def is_hex(s: str) -> bool:
|
1262
1319
|
return all(c in "0123456789abcdefABCDEF" for c in s)
|
@@ -14,6 +14,7 @@ from dbos import (
|
|
14
14
|
WorkflowStatusString,
|
15
15
|
_workflow_commands,
|
16
16
|
)
|
17
|
+
from dbos._app_db import ApplicationDatabase
|
17
18
|
from dbos._sys_db import SystemDatabase
|
18
19
|
from dbos._utils import GlobalParams
|
19
20
|
|
@@ -187,7 +188,9 @@ def test_get_workflow(dbos: DBOS, config: ConfigFile, sys_db: SystemDatabase) ->
|
|
187
188
|
assert info.workflow_id == wfUuid, f"Expected workflow_uuid to be {wfUuid}"
|
188
189
|
|
189
190
|
|
190
|
-
def test_queued_workflows(
|
191
|
+
def test_queued_workflows(
|
192
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
193
|
+
) -> None:
|
191
194
|
queued_steps = 5
|
192
195
|
step_events = [threading.Event() for _ in range(queued_steps)]
|
193
196
|
event = threading.Event()
|
@@ -292,7 +295,7 @@ def test_queued_workflows(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
292
295
|
assert len(workflows) == 0
|
293
296
|
|
294
297
|
# Test the steps are listed properly
|
295
|
-
steps = _workflow_commands.list_workflow_steps(sys_db, handle.workflow_id)
|
298
|
+
steps = _workflow_commands.list_workflow_steps(sys_db, app_db, handle.workflow_id)
|
296
299
|
assert len(steps) == queued_steps * 2
|
297
300
|
for i in range(queued_steps):
|
298
301
|
# Check the enqueues
|
@@ -311,7 +314,7 @@ def test_queued_workflows(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
311
314
|
child_workflows = DBOS.list_workflows(name=f"<temp>.{blocking_step.__qualname__}")
|
312
315
|
assert (len(child_workflows)) == queued_steps
|
313
316
|
for i, c in enumerate(child_workflows):
|
314
|
-
steps = _workflow_commands.list_workflow_steps(sys_db, c.workflow_id)
|
317
|
+
steps = _workflow_commands.list_workflow_steps(sys_db, app_db, c.workflow_id)
|
315
318
|
assert len(steps) == 1
|
316
319
|
assert steps[0]["function_id"] == 1
|
317
320
|
assert steps[0]["function_name"] == blocking_step.__qualname__
|
@@ -320,7 +323,9 @@ def test_queued_workflows(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
320
323
|
assert steps[0]["error"] is None
|
321
324
|
|
322
325
|
|
323
|
-
def test_list_2steps_sleep(
|
326
|
+
def test_list_2steps_sleep(
|
327
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
328
|
+
) -> None:
|
324
329
|
|
325
330
|
@DBOS.workflow()
|
326
331
|
def simple_workflow() -> None:
|
@@ -341,14 +346,16 @@ def test_list_2steps_sleep(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
341
346
|
with SetWorkflowID(wfid):
|
342
347
|
simple_workflow()
|
343
348
|
|
344
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
349
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
345
350
|
assert len(wfsteps) == 3
|
346
351
|
assert wfsteps[0]["function_name"] == stepOne.__qualname__
|
347
352
|
assert wfsteps[1]["function_name"] == stepTwo.__qualname__
|
348
353
|
assert wfsteps[2]["function_name"] == "DBOS.sleep"
|
349
354
|
|
350
355
|
|
351
|
-
def test_send_recv(
|
356
|
+
def test_send_recv(
|
357
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
358
|
+
) -> None:
|
352
359
|
|
353
360
|
@DBOS.workflow()
|
354
361
|
def send_workflow(target: str) -> None:
|
@@ -367,17 +374,19 @@ def test_send_recv(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
367
374
|
with SetWorkflowID(wfid_s):
|
368
375
|
send_workflow(wfid_r)
|
369
376
|
|
370
|
-
wfsteps_send = _workflow_commands.list_workflow_steps(sys_db, wfid_s)
|
377
|
+
wfsteps_send = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid_s)
|
371
378
|
assert len(wfsteps_send) == 1
|
372
379
|
assert wfsteps_send[0]["function_name"] == "DBOS.send"
|
373
380
|
|
374
|
-
wfsteps_recv = _workflow_commands.list_workflow_steps(sys_db, wfid_r)
|
381
|
+
wfsteps_recv = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid_r)
|
375
382
|
assert len(wfsteps_recv) == 2
|
376
|
-
assert wfsteps_recv[
|
377
|
-
assert wfsteps_recv[
|
383
|
+
assert wfsteps_recv[1]["function_name"] == "DBOS.sleep"
|
384
|
+
assert wfsteps_recv[0]["function_name"] == "DBOS.recv"
|
378
385
|
|
379
386
|
|
380
|
-
def test_set_get_event(
|
387
|
+
def test_set_get_event(
|
388
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
389
|
+
) -> None:
|
381
390
|
value = "Hello, World!"
|
382
391
|
|
383
392
|
@DBOS.workflow()
|
@@ -395,22 +404,24 @@ def test_set_get_event(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
395
404
|
with SetWorkflowID(wfid):
|
396
405
|
assert set_get_workflow() == value
|
397
406
|
|
398
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
407
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
399
408
|
assert len(wfsteps) == 5
|
400
409
|
assert wfsteps[0]["function_name"] == "DBOS.setEvent"
|
401
410
|
assert wfsteps[1]["function_name"] == stepOne.__qualname__
|
402
|
-
assert wfsteps[
|
403
|
-
assert wfsteps[
|
404
|
-
assert wfsteps[
|
405
|
-
assert wfsteps[
|
406
|
-
assert wfsteps[
|
411
|
+
assert wfsteps[3]["function_name"] == "DBOS.sleep"
|
412
|
+
assert wfsteps[2]["function_name"] == "DBOS.getEvent"
|
413
|
+
assert wfsteps[2]["child_workflow_id"] == None
|
414
|
+
assert wfsteps[2]["output"] == None
|
415
|
+
assert wfsteps[2]["error"] == None
|
407
416
|
assert wfsteps[4]["function_name"] == "DBOS.getEvent"
|
408
417
|
assert wfsteps[4]["child_workflow_id"] == None
|
409
418
|
assert wfsteps[4]["output"] == value
|
410
419
|
assert wfsteps[4]["error"] == None
|
411
420
|
|
412
421
|
|
413
|
-
def test_callchild_first_sync(
|
422
|
+
def test_callchild_first_sync(
|
423
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
424
|
+
) -> None:
|
414
425
|
|
415
426
|
@DBOS.workflow()
|
416
427
|
def parentWorkflow() -> str:
|
@@ -435,7 +446,7 @@ def test_callchild_first_sync(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
435
446
|
with SetWorkflowID(wfid):
|
436
447
|
child_id = parentWorkflow()
|
437
448
|
|
438
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
449
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
439
450
|
assert len(wfsteps) == 4
|
440
451
|
assert wfsteps[0]["function_name"] == child_workflow.__qualname__
|
441
452
|
assert wfsteps[0]["child_workflow_id"] == child_id
|
@@ -450,7 +461,9 @@ def test_callchild_first_sync(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
450
461
|
|
451
462
|
|
452
463
|
@pytest.mark.asyncio
|
453
|
-
async def test_callchild_direct_asyncio(
|
464
|
+
async def test_callchild_direct_asyncio(
|
465
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
466
|
+
) -> None:
|
454
467
|
|
455
468
|
@DBOS.workflow()
|
456
469
|
async def parentWorkflow() -> str:
|
@@ -475,7 +488,7 @@ async def test_callchild_direct_asyncio(dbos: DBOS, sys_db: SystemDatabase) -> N
|
|
475
488
|
with SetWorkflowID(wfid):
|
476
489
|
child_id = await parentWorkflow()
|
477
490
|
|
478
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
491
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
479
492
|
assert len(wfsteps) == 4
|
480
493
|
assert wfsteps[0]["function_name"] == child_workflow.__qualname__
|
481
494
|
assert wfsteps[0]["child_workflow_id"] == child_id
|
@@ -489,7 +502,9 @@ async def test_callchild_direct_asyncio(dbos: DBOS, sys_db: SystemDatabase) -> N
|
|
489
502
|
assert wfsteps[3]["function_name"] == stepTwo.__qualname__
|
490
503
|
|
491
504
|
|
492
|
-
def test_callchild_last_sync(
|
505
|
+
def test_callchild_last_sync(
|
506
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
507
|
+
) -> None:
|
493
508
|
|
494
509
|
@DBOS.workflow()
|
495
510
|
def parentWorkflow() -> None:
|
@@ -514,7 +529,7 @@ def test_callchild_last_sync(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
514
529
|
with SetWorkflowID(wfid):
|
515
530
|
parentWorkflow()
|
516
531
|
|
517
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
532
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
518
533
|
assert len(wfsteps) == 4
|
519
534
|
assert wfsteps[0]["function_name"] == stepOne.__qualname__
|
520
535
|
assert wfsteps[1]["function_name"] == stepTwo.__qualname__
|
@@ -522,7 +537,9 @@ def test_callchild_last_sync(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
522
537
|
assert wfsteps[3]["function_name"] == "DBOS.getResult"
|
523
538
|
|
524
539
|
|
525
|
-
def test_callchild_first_async_thread(
|
540
|
+
def test_callchild_first_async_thread(
|
541
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
542
|
+
) -> None:
|
526
543
|
|
527
544
|
@DBOS.workflow()
|
528
545
|
def parentWorkflow() -> None:
|
@@ -548,7 +565,7 @@ def test_callchild_first_async_thread(dbos: DBOS, sys_db: SystemDatabase) -> Non
|
|
548
565
|
with SetWorkflowID(wfid):
|
549
566
|
parentWorkflow()
|
550
567
|
|
551
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
568
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
552
569
|
assert len(wfsteps) == 4
|
553
570
|
assert wfsteps[0]["function_name"] == child_workflow.__qualname__
|
554
571
|
assert wfsteps[1]["function_name"] == "DBOS.getStatus"
|
@@ -556,7 +573,9 @@ def test_callchild_first_async_thread(dbos: DBOS, sys_db: SystemDatabase) -> Non
|
|
556
573
|
assert wfsteps[3]["function_name"] == stepTwo.__qualname__
|
557
574
|
|
558
575
|
|
559
|
-
def test_list_steps_errors(
|
576
|
+
def test_list_steps_errors(
|
577
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
578
|
+
) -> None:
|
560
579
|
queue = Queue("test-queue")
|
561
580
|
|
562
581
|
@DBOS.step()
|
@@ -582,7 +601,7 @@ def test_list_steps_errors(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
582
601
|
with SetWorkflowID(wfid):
|
583
602
|
with pytest.raises(Exception):
|
584
603
|
call_step()
|
585
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
604
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
586
605
|
assert len(wfsteps) == 1
|
587
606
|
assert wfsteps[0]["function_name"] == failing_step.__qualname__
|
588
607
|
assert wfsteps[0]["child_workflow_id"] == None
|
@@ -594,7 +613,7 @@ def test_list_steps_errors(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
594
613
|
with SetWorkflowID(wfid):
|
595
614
|
with pytest.raises(Exception):
|
596
615
|
start_step()
|
597
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
616
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
598
617
|
assert len(wfsteps) == 2
|
599
618
|
assert wfsteps[0]["function_name"] == f"<temp>.{failing_step.__qualname__}"
|
600
619
|
assert wfsteps[0]["child_workflow_id"] == f"{wfid}-1"
|
@@ -610,7 +629,7 @@ def test_list_steps_errors(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
610
629
|
with SetWorkflowID(wfid):
|
611
630
|
with pytest.raises(Exception):
|
612
631
|
enqueue_step()
|
613
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
632
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
614
633
|
assert len(wfsteps) == 2
|
615
634
|
assert wfsteps[0]["function_name"] == f"<temp>.{failing_step.__qualname__}"
|
616
635
|
assert wfsteps[0]["child_workflow_id"] == f"{wfid}-1"
|
@@ -623,7 +642,9 @@ def test_list_steps_errors(dbos: DBOS, sys_db: SystemDatabase) -> None:
|
|
623
642
|
|
624
643
|
|
625
644
|
@pytest.mark.asyncio
|
626
|
-
async def test_list_steps_errors_async(
|
645
|
+
async def test_list_steps_errors_async(
|
646
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
647
|
+
) -> None:
|
627
648
|
queue = Queue("test-queue")
|
628
649
|
|
629
650
|
@DBOS.step()
|
@@ -649,7 +670,7 @@ async def test_list_steps_errors_async(dbos: DBOS, sys_db: SystemDatabase) -> No
|
|
649
670
|
with SetWorkflowID(wfid):
|
650
671
|
with pytest.raises(Exception):
|
651
672
|
await call_step()
|
652
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
673
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
653
674
|
assert len(wfsteps) == 1
|
654
675
|
assert wfsteps[0]["function_name"] == failing_step.__qualname__
|
655
676
|
assert wfsteps[0]["child_workflow_id"] == None
|
@@ -661,7 +682,7 @@ async def test_list_steps_errors_async(dbos: DBOS, sys_db: SystemDatabase) -> No
|
|
661
682
|
with SetWorkflowID(wfid):
|
662
683
|
with pytest.raises(Exception):
|
663
684
|
await start_step()
|
664
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
685
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
665
686
|
assert len(wfsteps) == 2
|
666
687
|
assert wfsteps[0]["function_name"] == f"<temp>.{failing_step.__qualname__}"
|
667
688
|
assert wfsteps[0]["child_workflow_id"] == f"{wfid}-1"
|
@@ -677,7 +698,7 @@ async def test_list_steps_errors_async(dbos: DBOS, sys_db: SystemDatabase) -> No
|
|
677
698
|
with SetWorkflowID(wfid):
|
678
699
|
with pytest.raises(Exception):
|
679
700
|
await enqueue_step()
|
680
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
701
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
681
702
|
assert len(wfsteps) == 2
|
682
703
|
assert wfsteps[0]["function_name"] == f"<temp>.{failing_step.__qualname__}"
|
683
704
|
assert wfsteps[0]["child_workflow_id"] == f"{wfid}-1"
|
@@ -689,7 +710,9 @@ async def test_list_steps_errors_async(dbos: DBOS, sys_db: SystemDatabase) -> No
|
|
689
710
|
assert isinstance(wfsteps[1]["error"], Exception)
|
690
711
|
|
691
712
|
|
692
|
-
def test_callchild_middle_async_thread(
|
713
|
+
def test_callchild_middle_async_thread(
|
714
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
715
|
+
) -> None:
|
693
716
|
|
694
717
|
@DBOS.workflow()
|
695
718
|
def parentWorkflow() -> str:
|
@@ -716,7 +739,7 @@ def test_callchild_middle_async_thread(dbos: DBOS, sys_db: SystemDatabase) -> No
|
|
716
739
|
with SetWorkflowID(wfid):
|
717
740
|
child_id = parentWorkflow()
|
718
741
|
|
719
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
742
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
720
743
|
assert len(wfsteps) == 5
|
721
744
|
assert wfsteps[0]["function_name"] == stepOne.__qualname__
|
722
745
|
assert wfsteps[0]["child_workflow_id"] == None
|
@@ -738,7 +761,9 @@ def test_callchild_middle_async_thread(dbos: DBOS, sys_db: SystemDatabase) -> No
|
|
738
761
|
|
739
762
|
|
740
763
|
@pytest.mark.asyncio
|
741
|
-
async def test_callchild_first_asyncio(
|
764
|
+
async def test_callchild_first_asyncio(
|
765
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
766
|
+
) -> None:
|
742
767
|
|
743
768
|
@DBOS.workflow()
|
744
769
|
async def parentWorkflow() -> str:
|
@@ -765,7 +790,7 @@ async def test_callchild_first_asyncio(dbos: DBOS, sys_db: SystemDatabase) -> No
|
|
765
790
|
handle = await dbos.start_workflow_async(parentWorkflow)
|
766
791
|
child_id = await handle.get_result()
|
767
792
|
|
768
|
-
wfsteps = _workflow_commands.list_workflow_steps(sys_db, wfid)
|
793
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
769
794
|
assert len(wfsteps) == 4
|
770
795
|
assert wfsteps[0]["function_name"] == child_workflow.__qualname__
|
771
796
|
assert wfsteps[0]["child_workflow_id"] == child_id
|
@@ -856,3 +881,78 @@ async def test_callchild_rerun_asyncio(dbos: DBOS) -> None:
|
|
856
881
|
res2 = await handle.get_result()
|
857
882
|
|
858
883
|
assert res1 == res2
|
884
|
+
|
885
|
+
|
886
|
+
def test_list_transaction(
|
887
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
888
|
+
) -> None:
|
889
|
+
|
890
|
+
@DBOS.workflow()
|
891
|
+
def simple_workflow() -> None:
|
892
|
+
transactionOne()
|
893
|
+
stepTwo()
|
894
|
+
DBOS.sleep(1)
|
895
|
+
return
|
896
|
+
|
897
|
+
@DBOS.transaction()
|
898
|
+
def transactionOne() -> str:
|
899
|
+
return "a test transaction"
|
900
|
+
|
901
|
+
@DBOS.step()
|
902
|
+
def stepTwo() -> None:
|
903
|
+
return
|
904
|
+
|
905
|
+
wfid = str(uuid.uuid4())
|
906
|
+
with SetWorkflowID(wfid):
|
907
|
+
simple_workflow()
|
908
|
+
|
909
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
910
|
+
assert len(wfsteps) == 3
|
911
|
+
assert wfsteps[0]["function_name"] == transactionOne.__qualname__
|
912
|
+
assert wfsteps[0]["output"] == "a test transaction"
|
913
|
+
assert wfsteps[0]["error"] == None
|
914
|
+
assert wfsteps[1]["function_name"] == stepTwo.__qualname__
|
915
|
+
assert wfsteps[2]["function_name"] == "DBOS.sleep"
|
916
|
+
|
917
|
+
|
918
|
+
def test_list_transaction_error(
|
919
|
+
dbos: DBOS, sys_db: SystemDatabase, app_db: ApplicationDatabase
|
920
|
+
) -> None:
|
921
|
+
|
922
|
+
@DBOS.workflow()
|
923
|
+
def simple_workflow() -> None:
|
924
|
+
transactionOne()
|
925
|
+
stepTwo()
|
926
|
+
try:
|
927
|
+
transactionErr()
|
928
|
+
except Exception as e:
|
929
|
+
print(f"Error: {e}")
|
930
|
+
DBOS.sleep(1)
|
931
|
+
return
|
932
|
+
|
933
|
+
@DBOS.transaction()
|
934
|
+
def transactionOne() -> str:
|
935
|
+
return "a test transaction"
|
936
|
+
|
937
|
+
@DBOS.transaction()
|
938
|
+
def transactionErr() -> None:
|
939
|
+
raise Exception("a test transaction error")
|
940
|
+
|
941
|
+
@DBOS.step()
|
942
|
+
def stepTwo() -> None:
|
943
|
+
return
|
944
|
+
|
945
|
+
wfid = str(uuid.uuid4())
|
946
|
+
with SetWorkflowID(wfid):
|
947
|
+
simple_workflow()
|
948
|
+
|
949
|
+
wfsteps = _workflow_commands.list_workflow_steps(sys_db, app_db, wfid)
|
950
|
+
assert len(wfsteps) == 4
|
951
|
+
assert wfsteps[0]["function_name"] == transactionOne.__qualname__
|
952
|
+
assert wfsteps[0]["output"] == "a test transaction"
|
953
|
+
assert wfsteps[0]["error"] == None
|
954
|
+
assert wfsteps[1]["function_name"] == stepTwo.__qualname__
|
955
|
+
assert wfsteps[2]["function_name"] == transactionErr.__qualname__
|
956
|
+
assert wfsteps[2]["output"] == None
|
957
|
+
assert isinstance(wfsteps[2]["error"], Exception)
|
958
|
+
assert wfsteps[3]["function_name"] == "DBOS.sleep"
|
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
|
{dbos-0.26.0a5 → dbos-0.26.0a7}/dbos/_migrations/versions/5c361fc04708_added_system_tables.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
|