dbos 0.26.0a5__py3-none-any.whl → 0.26.0a7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dbos/_app_db.py +61 -2
- dbos/_conductor/conductor.py +1 -0
- dbos/_core.py +4 -0
- dbos/_dbos.py +6 -0
- dbos/_schemas/application_database.py +1 -0
- dbos/_workflow_commands.py +9 -3
- dbos/cli/cli.py +4 -1
- {dbos-0.26.0a5.dist-info → dbos-0.26.0a7.dist-info}/METADATA +1 -1
- {dbos-0.26.0a5.dist-info → dbos-0.26.0a7.dist-info}/RECORD +12 -12
- {dbos-0.26.0a5.dist-info → dbos-0.26.0a7.dist-info}/WHEEL +0 -0
- {dbos-0.26.0a5.dist-info → dbos-0.26.0a7.dist-info}/entry_points.txt +0 -0
- {dbos-0.26.0a5.dist-info → dbos-0.26.0a7.dist-info}/licenses/LICENSE +0 -0
dbos/_app_db.py
CHANGED
@@ -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
|
+
]
|
dbos/_conductor/conductor.py
CHANGED
dbos/_core.py
CHANGED
@@ -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
|
dbos/_dbos.py
CHANGED
@@ -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
|
|
dbos/_workflow_commands.py
CHANGED
@@ -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
|
dbos/cli/cli.py
CHANGED
@@ -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
|
|
@@ -1,23 +1,23 @@
|
|
1
|
-
dbos-0.26.
|
2
|
-
dbos-0.26.
|
3
|
-
dbos-0.26.
|
4
|
-
dbos-0.26.
|
1
|
+
dbos-0.26.0a7.dist-info/METADATA,sha256=PjY70KmfnbwPahIoEhiSsBEG6VLDOb972f59w0UWS3Q,5553
|
2
|
+
dbos-0.26.0a7.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
|
3
|
+
dbos-0.26.0a7.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
|
4
|
+
dbos-0.26.0a7.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
|
5
5
|
dbos/__init__.py,sha256=3NQfGlBiiUSM_v88STdVP3rNZvGkUL_9WbSotKb8Voo,873
|
6
6
|
dbos/__main__.py,sha256=G7Exn-MhGrVJVDbgNlpzhfh8WMX_72t3_oJaFT9Lmt8,653
|
7
7
|
dbos/_admin_server.py,sha256=vxPG_YJ6lYrkfPCSp42FiATVLBOij7Fm52Yngg5Z_tE,7027
|
8
|
-
dbos/_app_db.py,sha256=
|
8
|
+
dbos/_app_db.py,sha256=XdjZgKJMezSVZQJkvxBNa9x4asLURl2O-QxdmLai7wA,8491
|
9
9
|
dbos/_classproperty.py,sha256=f0X-_BySzn3yFDRKB2JpCbLYQ9tLwt1XftfshvY7CBs,626
|
10
10
|
dbos/_client.py,sha256=fzW_Gagh-oyWyDYtREcQDBesoVl_LsEoMeJAsn5-C5s,7262
|
11
11
|
dbos/_cloudutils/authentication.py,sha256=V0fCWQN9stCkhbuuxgPTGpvuQcDqfU3KAxPAh01vKW4,5007
|
12
12
|
dbos/_cloudutils/cloudutils.py,sha256=YC7jGsIopT0KveLsqbRpQk2KlRBk-nIRC_UCgep4f3o,7797
|
13
13
|
dbos/_cloudutils/databases.py,sha256=_shqaqSvhY4n2ScgQ8IP5PDZvzvcx3YBKV8fj-cxhSY,8543
|
14
|
-
dbos/_conductor/conductor.py,sha256=
|
14
|
+
dbos/_conductor/conductor.py,sha256=PzUFCX_JXGHClTF-hqTLR0ssO4kXdet4ZwHhJtuevEM,16839
|
15
15
|
dbos/_conductor/protocol.py,sha256=xN7pmooyF1pqbH1b6WhllU5718P7zSb_b0KCwA6bzcs,6716
|
16
16
|
dbos/_context.py,sha256=I8sLkdKTTkZEz7wG-MjynaQB6XEF2bLXuwNksiauP7w,19430
|
17
|
-
dbos/_core.py,sha256=
|
17
|
+
dbos/_core.py,sha256=EA9X4lTTTlimN8oa_mFICtl6Ke2biCvPdHl6PABjgGI,45749
|
18
18
|
dbos/_croniter.py,sha256=XHAyUyibs_59sJQfSNWkP7rqQY6_XrlfuuCxk4jYqek,47559
|
19
19
|
dbos/_db_wizard.py,sha256=VnMa6OL87Lc-XPDD1RnXp8NjsJE8YgiQLj3wtWAXp-8,8252
|
20
|
-
dbos/_dbos.py,sha256=
|
20
|
+
dbos/_dbos.py,sha256=je4LWR78S5uitxNzyf3k_x5KErEmXyu88TjqZnHtQXU,46183
|
21
21
|
dbos/_dbos_config.py,sha256=rTn30Hgh-RzTxqHbnYh2pC3Ioo30eJV9K4YxhJd-Gj4,22718
|
22
22
|
dbos/_debug.py,sha256=mmgvLkqlrljMBBow9wk01PPur9kUf2rI_11dTJXY4gw,1822
|
23
23
|
dbos/_error.py,sha256=B6Y9XLS1f6yrawxB2uAEYFMxFwk9BHhdxPNddKco-Fw,5399
|
@@ -44,7 +44,7 @@ dbos/_request.py,sha256=cX1B3Atlh160phgS35gF1VEEV4pD126c9F3BDgBmxZU,929
|
|
44
44
|
dbos/_roles.py,sha256=iOsgmIAf1XVzxs3gYWdGRe1B880YfOw5fpU7Jwx8_A8,2271
|
45
45
|
dbos/_scheduler.py,sha256=SR1oRZRcVzYsj-JauV2LA8JtwTkt8mru7qf6H1AzQ1U,2027
|
46
46
|
dbos/_schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
|
-
dbos/_schemas/application_database.py,sha256=
|
47
|
+
dbos/_schemas/application_database.py,sha256=SypAS9l9EsaBHFn9FR8jmnqt01M74d9AF1AMa4m2hhI,1040
|
48
48
|
dbos/_schemas/system_database.py,sha256=W9eSpL7SZzQkxcEZ4W07BOcwkkDr35b9oCjUOgfHWek,5336
|
49
49
|
dbos/_serialization.py,sha256=YCYv0qKAwAZ1djZisBC7khvKqG-5OcIv9t9EC5PFIog,1743
|
50
50
|
dbos/_sys_db.py,sha256=VBYVyKqZrwlFbDJ5cFIkeS5WtDOKpkI3lWJbSd5rB2s,65362
|
@@ -60,11 +60,11 @@ dbos/_templates/dbos-db-starter/migrations/versions/2024_07_31_180642_init.py,sh
|
|
60
60
|
dbos/_templates/dbos-db-starter/start_postgres_docker.py,sha256=lQVLlYO5YkhGPEgPqwGc7Y8uDKse9HsWv5fynJEFJHM,1681
|
61
61
|
dbos/_tracer.py,sha256=dFDSFlta-rfA3-ahIRLYwnnoAOmlavdxAGllqwFgnCA,2440
|
62
62
|
dbos/_utils.py,sha256=nFRUHzVjXG5AusF85AlYHikj63Tzi-kQm992ihsrAxA,201
|
63
|
-
dbos/_workflow_commands.py,sha256=
|
63
|
+
dbos/_workflow_commands.py,sha256=w981c3rVvhbhYd6BBP268C0Q88ClmwBwnachBxfnRmU,6129
|
64
64
|
dbos/cli/_github_init.py,sha256=Y_bDF9gfO2jB1id4FV5h1oIxEJRWyqVjhb7bNEa5nQ0,3224
|
65
65
|
dbos/cli/_template_init.py,sha256=-WW3kbq0W_Tq4WbMqb1UGJG3xvJb3woEY5VspG95Srk,2857
|
66
|
-
dbos/cli/cli.py,sha256=
|
66
|
+
dbos/cli/cli.py,sha256=FnI5ZAo-kAic-ij5wBqNJ2EJiYoBK1Ot-tTMh1WcXEM,16132
|
67
67
|
dbos/dbos-config.schema.json,sha256=4z2OXPfp7H0uNT1m5dKxjg31qbAfPyKkFXwHufuUMec,5910
|
68
68
|
dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
|
69
69
|
version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
|
70
|
-
dbos-0.26.
|
70
|
+
dbos-0.26.0a7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|