dbos 0.24.0a5__py3-none-any.whl → 0.24.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.

Potentially problematic release.


This version of dbos might be problematic. Click here for more details.

dbos/_app_db.py CHANGED
@@ -5,7 +5,7 @@ import sqlalchemy.dialects.postgresql as pg
5
5
  from sqlalchemy.exc import DBAPIError
6
6
  from sqlalchemy.orm import Session, sessionmaker
7
7
 
8
- from ._dbos_config import ConfigFile
8
+ from ._dbos_config import ConfigFile, DatabaseConfig
9
9
  from ._error import DBOSWorkflowConflictIDError
10
10
  from ._schemas.application_database import ApplicationSchema
11
11
 
@@ -61,8 +61,22 @@ class ApplicationDatabase:
61
61
  port=config["database"]["port"],
62
62
  database=app_db_name,
63
63
  )
64
+
65
+ connect_args = {}
66
+ if (
67
+ "connectionTimeoutMillis" in config["database"]
68
+ and config["database"]["connectionTimeoutMillis"]
69
+ ):
70
+ connect_args["connect_timeout"] = int(
71
+ config["database"]["connectionTimeoutMillis"] / 1000
72
+ )
73
+
64
74
  self.engine = sa.create_engine(
65
- app_db_url, pool_size=20, max_overflow=5, pool_timeout=30
75
+ app_db_url,
76
+ pool_size=config["database"]["app_db_pool_size"],
77
+ max_overflow=0,
78
+ pool_timeout=30,
79
+ connect_args=connect_args,
66
80
  )
67
81
  self.sessionmaker = sessionmaker(bind=self.engine)
68
82
  self.debug_mode = debug_mode
dbos/_core.py CHANGED
@@ -824,7 +824,9 @@ def decorate_step(
824
824
  stepOutcome = Outcome[R].make(functools.partial(func, *args, **kwargs))
825
825
  if retries_allowed:
826
826
  stepOutcome = stepOutcome.retry(
827
- max_attempts, on_exception, lambda i: DBOSMaxStepRetriesExceeded()
827
+ max_attempts,
828
+ on_exception,
829
+ lambda i: DBOSMaxStepRetriesExceeded(func.__name__, i),
828
830
  )
829
831
 
830
832
  outcome = (
dbos/_dbos.py CHANGED
@@ -457,7 +457,14 @@ class DBOS:
457
457
  admin_port = self.config.get("runtimeConfig", {}).get("admin_port")
458
458
  if admin_port is None:
459
459
  admin_port = 3001
460
- self._admin_server_field = AdminServer(dbos=self, port=admin_port)
460
+ run_admin_server = self.config.get("runtimeConfig", {}).get(
461
+ "run_admin_server"
462
+ )
463
+ if run_admin_server:
464
+ try:
465
+ self._admin_server_field = AdminServer(dbos=self, port=admin_port)
466
+ except Exception as e:
467
+ dbos_logger.warning(f"Failed to start admin server: {e}")
461
468
 
462
469
  workflow_ids = self._sys_db.get_pending_workflows(
463
470
  GlobalParams.executor_id, GlobalParams.app_version
dbos/_dbos_config.py CHANGED
@@ -22,30 +22,38 @@ from ._logger import dbos_logger
22
22
  DBOS_CONFIG_PATH = "dbos-config.yaml"
23
23
 
24
24
 
25
- class DBOSConfig(TypedDict):
25
+ class DBOSConfig(TypedDict, total=False):
26
26
  """
27
27
  Data structure containing the DBOS library configuration.
28
28
 
29
29
  Attributes:
30
30
  name (str): Application name
31
31
  database_url (str): Database connection string
32
+ app_db_pool_size (int): Application database pool size
32
33
  sys_db_name (str): System database name
34
+ sys_db_pool_size (int): System database pool size
33
35
  log_level (str): Log level
34
36
  otlp_traces_endpoints: List[str]: OTLP traces endpoints
37
+ admin_port (int): Admin port
38
+ run_admin_server (bool): Whether to run the DBOS admin server
35
39
  """
36
40
 
37
41
  name: str
38
42
  database_url: Optional[str]
43
+ app_db_pool_size: Optional[int]
39
44
  sys_db_name: Optional[str]
45
+ sys_db_pool_size: Optional[int]
40
46
  log_level: Optional[str]
41
47
  otlp_traces_endpoints: Optional[List[str]]
42
48
  admin_port: Optional[int]
49
+ run_admin_server: Optional[bool]
43
50
 
44
51
 
45
52
  class RuntimeConfig(TypedDict, total=False):
46
53
  start: List[str]
47
54
  setup: Optional[List[str]]
48
55
  admin_port: Optional[int]
56
+ run_admin_server: Optional[bool]
49
57
 
50
58
 
51
59
  class DatabaseConfig(TypedDict, total=False):
@@ -55,7 +63,9 @@ class DatabaseConfig(TypedDict, total=False):
55
63
  password: str
56
64
  connectionTimeoutMillis: Optional[int]
57
65
  app_db_name: str
66
+ app_db_pool_size: Optional[int]
58
67
  sys_db_name: Optional[str]
68
+ sys_db_pool_size: Optional[int]
59
69
  ssl: Optional[bool]
60
70
  ssl_ca: Optional[str]
61
71
  local_suffix: Optional[bool]
@@ -160,12 +170,21 @@ def translate_dbos_config_to_config_file(config: DBOSConfig) -> ConfigFile:
160
170
  db_config = parse_database_url_to_dbconfig(database_url)
161
171
  if "sys_db_name" in config:
162
172
  db_config["sys_db_name"] = config.get("sys_db_name")
173
+ if "app_db_pool_size" in config:
174
+ db_config["app_db_pool_size"] = config.get("app_db_pool_size")
175
+ if "sys_db_pool_size" in config:
176
+ db_config["sys_db_pool_size"] = config.get("sys_db_pool_size")
163
177
  if db_config:
164
178
  translated_config["database"] = db_config
165
179
 
166
- # Admin port
180
+ # Runtime config
181
+ translated_config["runtimeConfig"] = {"run_admin_server": True}
167
182
  if "admin_port" in config:
168
- translated_config["runtimeConfig"] = {"admin_port": config["admin_port"]}
183
+ translated_config["runtimeConfig"]["admin_port"] = config["admin_port"]
184
+ if "run_admin_server" in config:
185
+ translated_config["runtimeConfig"]["run_admin_server"] = config[
186
+ "run_admin_server"
187
+ ]
169
188
 
170
189
  # Telemetry config
171
190
  telemetry = {}
@@ -289,6 +308,15 @@ def process_config(
289
308
  f'Invalid app name {data["name"]}. App names must be between 3 and 30 characters long and contain only lowercase letters, numbers, dashes, and underscores.'
290
309
  )
291
310
 
311
+ if data.get("telemetry") is None:
312
+ data["telemetry"] = {}
313
+ telemetry = cast(TelemetryConfig, data["telemetry"])
314
+ if telemetry.get("logs") is None:
315
+ telemetry["logs"] = {}
316
+ logs = cast(LoggerConfig, telemetry["logs"])
317
+ if logs.get("logLevel") is None:
318
+ logs["logLevel"] = "INFO"
319
+
292
320
  if "database" not in data:
293
321
  data["database"] = {}
294
322
 
@@ -379,6 +407,20 @@ def process_config(
379
407
  local_suffix = dbos_dblocalsuffix
380
408
  data["database"]["local_suffix"] = local_suffix
381
409
 
410
+ if not data["database"].get("app_db_pool_size"):
411
+ data["database"]["app_db_pool_size"] = 20
412
+ if not data["database"].get("sys_db_pool_size"):
413
+ data["database"]["sys_db_pool_size"] = 20
414
+ if not data["database"].get("connectionTimeoutMillis"):
415
+ data["database"]["connectionTimeoutMillis"] = 10000
416
+
417
+ if not data.get("runtimeConfig"):
418
+ data["runtimeConfig"] = {
419
+ "run_admin_server": True,
420
+ }
421
+ elif "run_admin_server" not in data["runtimeConfig"]:
422
+ data["runtimeConfig"]["run_admin_server"] = True
423
+
382
424
  # Check the connectivity to the database and make sure it's properly configured
383
425
  # Note, never use db wizard if the DBOS is running in debug mode (i.e. DBOS_DEBUG_WORKFLOW_ID env var is set)
384
426
  debugWorkflowId = os.getenv("DBOS_DEBUG_WORKFLOW_ID")
@@ -475,13 +517,13 @@ def overwrite_config(provided_config: ConfigFile) -> ConfigFile:
475
517
  otlp_exporter["logsEndpoint"] = logsEndpoint
476
518
 
477
519
  # Runtime config
478
- if (
479
- "runtimeConfig" in provided_config
480
- and "admin_port" in provided_config["runtimeConfig"]
481
- ):
482
- del provided_config["runtimeConfig"][
483
- "admin_port"
484
- ] # Admin port is expected to be 3001 (the default in dbos/_admin_server.py::__init__ ) by DBOS Cloud
520
+ if "runtimeConfig" in provided_config:
521
+ if "admin_port" in provided_config["runtimeConfig"]:
522
+ del provided_config["runtimeConfig"][
523
+ "admin_port"
524
+ ] # Admin port is expected to be 3001 (the default in dbos/_admin_server.py::__init__ ) by DBOS Cloud
525
+ if "run_admin_server" in provided_config["runtimeConfig"]:
526
+ del provided_config["runtimeConfig"]["run_admin_server"]
485
527
 
486
528
  # Env should be set from the hosting provider (e.g., DBOS Cloud)
487
529
  if "env" in provided_config:
dbos/_error.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Errors thrown by DBOS."""
2
2
 
3
3
  from enum import Enum
4
- from typing import Optional
4
+ from typing import Any, Optional
5
5
 
6
6
 
7
7
  class DBOSException(Exception):
@@ -124,12 +124,18 @@ class DBOSNotAuthorizedError(DBOSException):
124
124
  class DBOSMaxStepRetriesExceeded(DBOSException):
125
125
  """Exception raised when a step was retried the maximimum number of times without success."""
126
126
 
127
- def __init__(self) -> None:
127
+ def __init__(self, step_name: str, max_retries: int) -> None:
128
+ self.step_name = step_name
129
+ self.max_retries = max_retries
128
130
  super().__init__(
129
- "Step reached maximum retries.",
131
+ f"Step {step_name} has exceeded its maximum of {max_retries} retries",
130
132
  dbos_error_code=DBOSErrorCode.MaxStepRetriesExceeded.value,
131
133
  )
132
134
 
135
+ def __reduce__(self) -> Any:
136
+ # Tell jsonpickle how to reconstruct this object
137
+ return (self.__class__, (self.step_name, self.max_retries))
138
+
133
139
 
134
140
  class DBOSWorkflowCancelledError(DBOSException):
135
141
  """Exception raised when the workflow has already been cancelled."""
dbos/_sys_db.py CHANGED
@@ -203,8 +203,8 @@ class SystemDatabase:
203
203
  # Create a connection pool for the system database
204
204
  self.engine = sa.create_engine(
205
205
  system_db_url,
206
- pool_size=20,
207
- max_overflow=5,
206
+ pool_size=config["database"]["sys_db_pool_size"],
207
+ max_overflow=0,
208
208
  pool_timeout=30,
209
209
  connect_args={"connect_timeout": 10},
210
210
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 0.24.0a5
3
+ Version: 0.24.0a7
4
4
  Summary: Ultra-lightweight durable execution in Python
5
5
  Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
6
  License: MIT
@@ -1,11 +1,11 @@
1
- dbos-0.24.0a5.dist-info/METADATA,sha256=Dg70KhSEysG1pJLOV16tY2B_631JRLjMg5LbkF78HeM,5555
2
- dbos-0.24.0a5.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- dbos-0.24.0a5.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
- dbos-0.24.0a5.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
1
+ dbos-0.24.0a7.dist-info/METADATA,sha256=wvDZ3P2eE7j7S3YM33RoAxO3Sp0R9woyTrAC1wCEvdE,5555
2
+ dbos-0.24.0a7.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ dbos-0.24.0a7.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
+ dbos-0.24.0a7.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
5
5
  dbos/__init__.py,sha256=uq9LP5uY96kIS9N0yKqlvDwADmtg_Hl30uSUhyuUr-4,754
6
6
  dbos/__main__.py,sha256=P7jAr-7L9XE5mrsQ7i4b-bLr2ap1tCQfhMByLCRWDj0,568
7
7
  dbos/_admin_server.py,sha256=YiVn5lywz2Vg8_juyNHOYl0HVEy48--7b4phwK7r92o,5732
8
- dbos/_app_db.py,sha256=QFL1ceCugJFj_LBvK_G_0tt5jjyTM-4KnqmhbuC1ggg,5826
8
+ dbos/_app_db.py,sha256=4EGrYL14rVx96TXn34hoibN9ltf4-2DKcj6nd-HvBxA,6262
9
9
  dbos/_classproperty.py,sha256=f0X-_BySzn3yFDRKB2JpCbLYQ9tLwt1XftfshvY7CBs,626
10
10
  dbos/_cloudutils/authentication.py,sha256=V0fCWQN9stCkhbuuxgPTGpvuQcDqfU3KAxPAh01vKW4,5007
11
11
  dbos/_cloudutils/cloudutils.py,sha256=YC7jGsIopT0KveLsqbRpQk2KlRBk-nIRC_UCgep4f3o,7797
@@ -13,13 +13,13 @@ dbos/_cloudutils/databases.py,sha256=_shqaqSvhY4n2ScgQ8IP5PDZvzvcx3YBKV8fj-cxhSY
13
13
  dbos/_conductor/conductor.py,sha256=tvB1k8V3ZsI3MBEcG9sIkfbsHHx_Cvh0FZAi9vSPrXU,12698
14
14
  dbos/_conductor/protocol.py,sha256=Lo-DjvKevTS2uKyITLjjVp56rBRzaQfKkKpieZz3VAs,5088
15
15
  dbos/_context.py,sha256=Ue5qu3rzLfRmPkz-UUZi9ZS8iXpapRN0NTM4mbA2QmQ,17738
16
- dbos/_core.py,sha256=UQb068FT59Op-F5RmtxreSeSQ1_wljOso0dQCUOPrC4,37528
16
+ dbos/_core.py,sha256=8TTIj5shcm5hpKjouMA4VzMWl7R7MJlU-mAHB6xQBxE,37585
17
17
  dbos/_croniter.py,sha256=XHAyUyibs_59sJQfSNWkP7rqQY6_XrlfuuCxk4jYqek,47559
18
18
  dbos/_db_wizard.py,sha256=YEW2qoy6hfHQv2fZ_4nHiPUeHMFofPpNTolJ1Kvw7AQ,8394
19
- dbos/_dbos.py,sha256=2A1_5Fjv54G_bNKpSsYOFwEXDWJcaM-x1i2sY_h581w,42523
20
- dbos/_dbos_config.py,sha256=MJOJu0dCzdcxJi2gUMkTcJaxm_XVr2a2Dfq7vL_nEL0,17844
19
+ dbos/_dbos.py,sha256=AiTuQYoaq9H5qH2dMsIVwNsF645PjBWzj9rjpa9snwo,42824
20
+ dbos/_dbos_config.py,sha256=GEjS_EfRIVHBiQDn0tcVftg8pesKFkIP5HuqajAJ9rA,19751
21
21
  dbos/_debug.py,sha256=mmgvLkqlrljMBBow9wk01PPur9kUf2rI_11dTJXY4gw,1822
22
- dbos/_error.py,sha256=xqB7b7g5AF_OwOvqLKLXL1xldn2gAtORix2ZC2B8zK0,5089
22
+ dbos/_error.py,sha256=B6Y9XLS1f6yrawxB2uAEYFMxFwk9BHhdxPNddKco-Fw,5399
23
23
  dbos/_fastapi.py,sha256=ke03vqsSYDnO6XeOtOVFXj0-f-v1MGsOxa9McaROvNc,3616
24
24
  dbos/_flask.py,sha256=DZKUZR5-xOzPI7tYZ53r2PvvHVoAb8SYwLzMVFsVfjI,2608
25
25
  dbos/_kafka.py,sha256=o6DbwnsYRDtvVTZVsN7BAK8cdP79AfoWX3Q7CGY2Yuo,4199
@@ -45,7 +45,7 @@ dbos/_schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
45
  dbos/_schemas/application_database.py,sha256=KeyoPrF7hy_ODXV7QNike_VFSD74QBRfQ76D7QyE9HI,966
46
46
  dbos/_schemas/system_database.py,sha256=16146P4TLjAGjTYykOs_KUd2c_geJ5fuhk0ko85C65M,5211
47
47
  dbos/_serialization.py,sha256=YCYv0qKAwAZ1djZisBC7khvKqG-5OcIv9t9EC5PFIog,1743
48
- dbos/_sys_db.py,sha256=qzVPkg64fvTwDGOI_ATQ4JySiH6szyo6NmRrZaCeDwQ,64674
48
+ dbos/_sys_db.py,sha256=blR_kOrcDFe11OfIYHzTQ-a9ptuXJEwO5lGTh2PTHAs,64710
49
49
  dbos/_templates/dbos-db-starter/README.md,sha256=GhxhBj42wjTt1fWEtwNriHbJuKb66Vzu89G4pxNHw2g,930
50
50
  dbos/_templates/dbos-db-starter/__package/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
51
  dbos/_templates/dbos-db-starter/__package/main.py,sha256=eI0SS9Nwj-fldtiuSzIlIG6dC91GXXwdRsoHxv6S_WI,2719
@@ -65,4 +65,4 @@ dbos/cli/cli.py,sha256=ThomRytw7EP5iOcrjEgwnpaWgXNTLfnFEBBvCGHxtJs,15590
65
65
  dbos/dbos-config.schema.json,sha256=HtF_njVTGHLdzBGZ4OrGQz3qbPPT0Go-iwd1PgFVTNg,5847
66
66
  dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
67
67
  version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
68
- dbos-0.24.0a5.dist-info/RECORD,,
68
+ dbos-0.24.0a7.dist-info/RECORD,,