dbos 1.13.0a5__py3-none-any.whl → 1.13.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
@@ -383,7 +383,6 @@ class SQLiteApplicationDatabase(ApplicationDatabase):
383
383
  ).fetchone()
384
384
 
385
385
  if result is None:
386
- # Create the table with proper SQLite syntax
387
386
  conn.execute(
388
387
  sa.text(
389
388
  f"""
@@ -402,7 +401,6 @@ class SQLiteApplicationDatabase(ApplicationDatabase):
402
401
  """
403
402
  )
404
403
  )
405
- # Create the index
406
404
  conn.execute(
407
405
  sa.text(
408
406
  "CREATE INDEX transaction_outputs_created_at_index ON transaction_outputs (created_at)"
dbos/_client.py CHANGED
@@ -25,7 +25,11 @@ else:
25
25
 
26
26
  from dbos import _serialization
27
27
  from dbos._dbos import WorkflowHandle, WorkflowHandleAsync
28
- from dbos._dbos_config import get_system_database_url, is_valid_database_url
28
+ from dbos._dbos_config import (
29
+ get_application_database_url,
30
+ get_system_database_url,
31
+ is_valid_database_url,
32
+ )
29
33
  from dbos._error import DBOSException, DBOSNonExistentWorkflowError
30
34
  from dbos._registrations import DEFAULT_MAX_RECOVERY_ATTEMPTS
31
35
  from dbos._serialization import WorkflowInputs
@@ -113,21 +117,32 @@ class WorkflowHandleClientAsyncPolling(Generic[R]):
113
117
  class DBOSClient:
114
118
  def __init__(
115
119
  self,
116
- database_url: str,
120
+ database_url: Optional[str] = None, # DEPRECATED
117
121
  *,
118
122
  system_database_url: Optional[str] = None,
119
- system_database: Optional[str] = None,
123
+ application_database_url: Optional[str] = None,
124
+ system_database: Optional[str] = None, # DEPRECATED
120
125
  ):
121
- assert is_valid_database_url(database_url)
126
+ application_database_url = get_application_database_url(
127
+ {
128
+ "system_database_url": system_database_url,
129
+ "database_url": (
130
+ database_url if database_url else application_database_url
131
+ ),
132
+ }
133
+ )
134
+ system_database_url = get_system_database_url(
135
+ {
136
+ "system_database_url": system_database_url,
137
+ "database_url": application_database_url,
138
+ "database": {"sys_db_name": system_database},
139
+ }
140
+ )
141
+ assert is_valid_database_url(system_database_url)
142
+ assert is_valid_database_url(application_database_url)
122
143
  # We only create database connections but do not run migrations
123
144
  self._sys_db = SystemDatabase.create(
124
- system_database_url=get_system_database_url(
125
- {
126
- "system_database_url": system_database_url,
127
- "database_url": database_url,
128
- "database": {"sys_db_name": system_database},
129
- }
130
- ),
145
+ system_database_url=system_database_url,
131
146
  engine_kwargs={
132
147
  "pool_timeout": 30,
133
148
  "max_overflow": 0,
@@ -136,14 +151,13 @@ class DBOSClient:
136
151
  )
137
152
  self._sys_db.check_connection()
138
153
  self._app_db = ApplicationDatabase.create(
139
- database_url=database_url,
154
+ database_url=application_database_url,
140
155
  engine_kwargs={
141
156
  "pool_timeout": 30,
142
157
  "max_overflow": 0,
143
158
  "pool_size": 2,
144
159
  },
145
160
  )
146
- self._db_url = database_url
147
161
 
148
162
  def destroy(self) -> None:
149
163
  self._sys_db.destroy()
dbos/_dbos_config.py CHANGED
@@ -22,9 +22,10 @@ class DBOSConfig(TypedDict, total=False):
22
22
 
23
23
  Attributes:
24
24
  name (str): Application name
25
- database_url (str): Database connection string
26
- system_database_url (str): Connection string for the system database (if different from the application database)
27
- sys_db_name (str): System database name (deprecated)
25
+ system_database_url (str): Connection string for the DBOS system database. Defaults to sqlite:///{name} if not provided.
26
+ application_database_url (str): Connection string for the DBOS application database, in which DBOS @Transaction functions run. Optional. Should be the same type of database (SQLite or Postgres) as the system database.
27
+ database_url (str): (DEPRECATED) Database connection string
28
+ sys_db_name (str): (DEPRECATED) System database name
28
29
  sys_db_pool_size (int): System database pool size
29
30
  db_engine_kwargs (Dict[str, Any]): SQLAlchemy engine kwargs (See https://docs.sqlalchemy.org/en/20/core/engines.html#sqlalchemy.create_engine)
30
31
  log_level (str): Log level
@@ -39,8 +40,9 @@ class DBOSConfig(TypedDict, total=False):
39
40
  """
40
41
 
41
42
  name: str
42
- database_url: Optional[str]
43
43
  system_database_url: Optional[str]
44
+ application_database_url: Optional[str]
45
+ database_url: Optional[str]
44
46
  sys_db_name: Optional[str]
45
47
  sys_db_pool_size: Optional[int]
46
48
  db_engine_kwargs: Optional[Dict[str, Any]]
@@ -107,12 +109,12 @@ class ConfigFile(TypedDict, total=False):
107
109
 
108
110
  Attributes:
109
111
  name (str): Application name
110
- runtimeConfig (RuntimeConfig): Configuration for request serving
112
+ runtimeConfig (RuntimeConfig): Configuration for DBOS Cloud
111
113
  database (DatabaseConfig): Configure pool sizes, migrate commands
112
- database_url (str): Database connection string
114
+ database_url (str): Application database URL
115
+ system_database_url (str): System database URL
113
116
  telemetry (TelemetryConfig): Configuration for tracing / logging
114
- env (Dict[str,str]): Environment varialbes
115
- application (Dict[str, Any]): Application-specific configuration section
117
+ env (Dict[str,str]): Environment variables
116
118
 
117
119
  """
118
120
 
@@ -144,8 +146,12 @@ def translate_dbos_config_to_config_file(config: DBOSConfig) -> ConfigFile:
144
146
  if db_config:
145
147
  translated_config["database"] = db_config
146
148
 
149
+ # Use application_database_url instead of the deprecated database_url if provided
147
150
  if "database_url" in config:
148
151
  translated_config["database_url"] = config.get("database_url")
152
+ elif "application_database_url" in config:
153
+ translated_config["database_url"] = config.get("application_database_url")
154
+
149
155
  if "system_database_url" in config:
150
156
  translated_config["system_database_url"] = config.get("system_database_url")
151
157
 
@@ -233,7 +239,6 @@ def _substitute_env_vars(content: str, silent: bool = False) -> str:
233
239
  def load_config(
234
240
  config_file_path: str = DBOS_CONFIG_PATH,
235
241
  *,
236
- run_process_config: bool = True,
237
242
  silent: bool = False,
238
243
  ) -> ConfigFile:
239
244
  """
@@ -283,8 +288,6 @@ def load_config(
283
288
  ]
284
289
 
285
290
  data = cast(ConfigFile, data)
286
- if run_process_config:
287
- data = process_config(data=data, silent=silent)
288
291
  return data # type: ignore
289
292
 
290
293
 
@@ -333,25 +336,16 @@ def process_config(
333
336
 
334
337
  # Ensure database dict exists
335
338
  data.setdefault("database", {})
336
-
337
- # Database URL resolution
338
339
  connect_timeout = None
339
- if data.get("database_url") is not None and data["database_url"] != "":
340
+
341
+ # Process the application database URL, if provided
342
+ if data.get("database_url"):
340
343
  # Parse the db string and check required fields
341
344
  assert data["database_url"] is not None
342
345
  assert is_valid_database_url(data["database_url"])
343
346
 
344
347
  url = make_url(data["database_url"])
345
348
 
346
- if data["database_url"].startswith("sqlite"):
347
- data["system_database_url"] = data["database_url"]
348
- else:
349
- assert url.database is not None
350
- if not data["database"].get("sys_db_name"):
351
- data["database"]["sys_db_name"] = (
352
- url.database + SystemSchema.sysdb_suffix
353
- )
354
-
355
349
  # Gather connect_timeout from the URL if provided. It should be used in engine kwargs if not provided there (instead of our default)
356
350
  connect_timeout_str = url.query.get("connect_timeout")
357
351
  if connect_timeout_str is not None:
@@ -376,18 +370,80 @@ def process_config(
376
370
  host=os.getenv("DBOS_DBHOST", url.host),
377
371
  port=port,
378
372
  ).render_as_string(hide_password=False)
379
- else:
373
+
374
+ # Process the system database URL, if provided
375
+ if data.get("system_database_url"):
376
+ # Parse the db string and check required fields
377
+ assert data["system_database_url"]
378
+ assert is_valid_database_url(data["system_database_url"])
379
+
380
+ url = make_url(data["system_database_url"])
381
+
382
+ # Gather connect_timeout from the URL if provided. It should be used in engine kwargs if not provided there (instead of our default). This overrides a timeout from the application database, if any.
383
+ connect_timeout_str = url.query.get("connect_timeout")
384
+ if connect_timeout_str is not None:
385
+ assert isinstance(
386
+ connect_timeout_str, str
387
+ ), "connect_timeout must be a string and defined once in the URL"
388
+ if connect_timeout_str.isdigit():
389
+ connect_timeout = int(connect_timeout_str)
390
+
391
+ # In debug mode perform env vars overrides
392
+ if isDebugMode:
393
+ # Override the username, password, host, and port
394
+ port_str = os.getenv("DBOS_DBPORT")
395
+ port = (
396
+ int(port_str)
397
+ if port_str is not None and port_str.isdigit()
398
+ else url.port
399
+ )
400
+ data["system_database_url"] = url.set(
401
+ username=os.getenv("DBOS_DBUSER", url.username),
402
+ password=os.getenv("DBOS_DBPASSWORD", url.password),
403
+ host=os.getenv("DBOS_DBHOST", url.host),
404
+ port=port,
405
+ ).render_as_string(hide_password=False)
406
+
407
+ # If an application database URL is provided but not the system database URL,
408
+ # construct the system database URL.
409
+ if data.get("database_url") and not data.get("system_database_url"):
410
+ assert data["database_url"]
411
+ if data["database_url"].startswith("sqlite"):
412
+ data["system_database_url"] = data["database_url"]
413
+ else:
414
+ url = make_url(data["database_url"])
415
+ assert url.database
416
+ if data["database"].get("sys_db_name"):
417
+ url = url.set(database=data["database"]["sys_db_name"])
418
+ else:
419
+ url = url.set(database=f"{url.database}{SystemSchema.sysdb_suffix}")
420
+ data["system_database_url"] = url.render_as_string(hide_password=False)
421
+
422
+ # If a system database URL is provided but not an application database URL, set the
423
+ # application database URL to the system database URL.
424
+ if data.get("system_database_url") and not data.get("database_url"):
425
+ assert data["system_database_url"]
426
+ data["database_url"] = data["system_database_url"]
427
+
428
+ # If neither URL is provided, use a default SQLite database URL.
429
+ if not data.get("database_url") and not data.get("system_database_url"):
380
430
  _app_db_name = _app_name_to_db_name(data["name"])
381
- data["database_url"] = f"sqlite:///{_app_db_name}.sqlite"
382
- data["system_database_url"] = data["database_url"]
431
+ data["system_database_url"] = data["database_url"] = (
432
+ f"sqlite:///{_app_db_name}.sqlite"
433
+ )
383
434
 
384
435
  configure_db_engine_parameters(data["database"], connect_timeout=connect_timeout)
385
436
 
386
- # Pretty-print where we've loaded database connection information from, respecting the log level
387
437
  assert data["database_url"] is not None
438
+ assert data["system_database_url"] is not None
439
+ # Pretty-print connection information, respecting log level
388
440
  if not silent and logs["logLevel"] == "INFO" or logs["logLevel"] == "DEBUG":
389
- log_url = make_url(data["database_url"]).render_as_string(hide_password=True)
390
- print(f"[bold blue]Using database connection string: {log_url}[/bold blue]")
441
+ printable_sys_db_url = make_url(data["system_database_url"]).render_as_string(
442
+ hide_password=True
443
+ )
444
+ print(
445
+ f"[bold blue]DBOS system database URL: {printable_sys_db_url}[/bold blue]"
446
+ )
391
447
  if data["database_url"].startswith("sqlite"):
392
448
  print(
393
449
  f"[bold blue]Using SQLite as a system database. The SQLite system database is for development and testing. PostgreSQL is recommended for production use.[/bold blue]"
@@ -474,36 +530,34 @@ def _app_name_to_db_name(app_name: str) -> str:
474
530
 
475
531
  def overwrite_config(provided_config: ConfigFile) -> ConfigFile:
476
532
  # Load the DBOS configuration file and force the use of:
477
- # 1. The database url provided by DBOS_DATABASE_URL
533
+ # 1. The application and system database url provided by DBOS_DATABASE_URL and DBOS_SYSTEM_DATABASE_URL
478
534
  # 2. OTLP traces endpoints (add the config data to the provided config)
479
535
  # 3. Use the application name from the file. This is a defensive measure to ensure the application name is whatever it was registered with in the cloud
480
536
  # 4. Remove admin_port is provided in code
481
537
  # 5. Remove env vars if provided in code
482
538
  # Optimistically assume that expected fields in config_from_file are present
483
539
 
484
- config_from_file = load_config(run_process_config=False)
540
+ config_from_file = load_config()
485
541
  # Be defensive
486
542
  if config_from_file is None:
487
543
  return provided_config
488
544
 
489
- # Name
545
+ # Set the application name to the cloud app name
490
546
  provided_config["name"] = config_from_file["name"]
491
547
 
492
- # Database config. Expects DBOS_DATABASE_URL to be set
493
- if "database" not in provided_config:
494
- provided_config["database"] = {}
495
- provided_config["database"]["sys_db_name"] = config_from_file["database"][
496
- "sys_db_name"
497
- ]
498
-
548
+ # Use the DBOS Cloud application and system database URLs
499
549
  db_url = os.environ.get("DBOS_DATABASE_URL")
500
550
  if db_url is None:
501
551
  raise DBOSInitializationError(
502
552
  "DBOS_DATABASE_URL environment variable is not set. This is required to connect to the database."
503
553
  )
504
554
  provided_config["database_url"] = db_url
505
- if "system_database_url" in provided_config:
506
- del provided_config["system_database_url"]
555
+ system_db_url = os.environ.get("DBOS_SYSTEM_DATABASE_URL")
556
+ if system_db_url is None:
557
+ raise DBOSInitializationError(
558
+ "DBOS_SYSTEM_DATABASE_URL environment variable is not set. This is required to connect to the database."
559
+ )
560
+ provided_config["system_database_url"] = system_db_url
507
561
 
508
562
  # Telemetry config
509
563
  if "telemetry" not in provided_config or provided_config["telemetry"] is None:
@@ -563,7 +617,7 @@ def get_system_database_url(config: ConfigFile) -> str:
563
617
  if config["database_url"].startswith("sqlite"):
564
618
  return config["database_url"]
565
619
  app_db_url = make_url(config["database_url"])
566
- if config["database"].get("sys_db_name") is not None:
620
+ if config.get("database") and config["database"].get("sys_db_name") is not None:
567
621
  sys_db_name = config["database"]["sys_db_name"]
568
622
  else:
569
623
  assert app_db_url.database is not None
@@ -571,3 +625,14 @@ def get_system_database_url(config: ConfigFile) -> str:
571
625
  return app_db_url.set(database=sys_db_name).render_as_string(
572
626
  hide_password=False
573
627
  )
628
+
629
+
630
+ def get_application_database_url(config: ConfigFile) -> str:
631
+ # For backwards compatibility, the application database URL is "database_url"
632
+ if config.get("database_url"):
633
+ assert config["database_url"]
634
+ return config["database_url"]
635
+ else:
636
+ # If the application database URL is not specified, set it to the system database URL
637
+ assert config["system_database_url"]
638
+ return config["system_database_url"]
dbos/_sys_db.py CHANGED
@@ -1422,7 +1422,6 @@ class SystemDatabase(ABC):
1422
1422
  debug_mode=debug_mode,
1423
1423
  )
1424
1424
  else:
1425
- # Default to PostgreSQL for postgresql://, postgres://, or other URLs
1426
1425
  from ._sys_db_postgres import PostgresSystemDatabase
1427
1426
 
1428
1427
  return PostgresSystemDatabase(
dbos/_sys_db_sqlite.py CHANGED
@@ -92,18 +92,15 @@ class SQLiteSystemDatabase(SystemDatabase):
92
92
  last_applied = i
93
93
 
94
94
  def _cleanup_connections(self) -> None:
95
- """Clean up SQLite-specific connections."""
96
95
  # SQLite doesn't require special connection cleanup
97
96
  pass
98
97
 
99
98
  def _is_unique_constraint_violation(self, dbapi_error: DBAPIError) -> bool:
100
99
  """Check if the error is a unique constraint violation in SQLite."""
101
- # SQLite UNIQUE constraint error
102
100
  return "UNIQUE constraint failed" in str(dbapi_error.orig)
103
101
 
104
102
  def _is_foreign_key_violation(self, dbapi_error: DBAPIError) -> bool:
105
103
  """Check if the error is a foreign key violation in SQLite."""
106
- # SQLite FOREIGN KEY constraint error
107
104
  return "FOREIGN KEY constraint failed" in str(dbapi_error.orig)
108
105
 
109
106
  @staticmethod
dbos/cli/cli.py CHANGED
@@ -5,7 +5,7 @@ import subprocess
5
5
  import time
6
6
  import typing
7
7
  from os import path
8
- from typing import Any, Optional
8
+ from typing import Any, Optional, Tuple
9
9
 
10
10
  import jsonpickle # type: ignore
11
11
  import sqlalchemy as sa
@@ -18,62 +18,65 @@ from dbos._context import SetWorkflowID
18
18
  from dbos._debug import debug_workflow, parse_start_command
19
19
  from dbos.cli.migration import grant_dbos_schema_permissions, migrate_dbos_databases
20
20
 
21
- from .._app_db import ApplicationDatabase
22
21
  from .._client import DBOSClient
23
22
  from .._dbos_config import (
23
+ ConfigFile,
24
24
  _app_name_to_db_name,
25
25
  _is_valid_app_name,
26
+ get_application_database_url,
26
27
  get_system_database_url,
27
- is_valid_database_url,
28
28
  load_config,
29
29
  )
30
30
  from .._docker_pg_helper import start_docker_pg, stop_docker_pg
31
- from .._schemas.system_database import SystemSchema
32
31
  from .._sys_db import SystemDatabase
33
32
  from .._utils import GlobalParams
34
33
  from ..cli._github_init import create_template_from_github
35
34
  from ._template_init import copy_template, get_project_name, get_templates_directory
36
35
 
37
36
 
38
- def _get_db_url(db_url: Optional[str]) -> str:
37
+ def _get_db_url(
38
+ *, system_database_url: Optional[str], application_database_url: Optional[str]
39
+ ) -> Tuple[str, str]:
39
40
  """
40
41
  Get the database URL to use for the DBOS application.
41
42
  Order of precedence:
42
- - If the `db_url` argument is provided, use it.
43
- - If the `dbos-config.yaml` file is present, use the `database_url` from it.
44
- - If the `DBOS_DATABASE_URL` environment variable is set, use it.
43
+ - In DBOS Cloud, use the environment variables provided.
44
+ - Use database URL arguments if provided.
45
+ - If the `dbos-config.yaml` file is present, use the database URLs from it.
45
46
 
46
- Otherwise fallback to the same default Postgres URL than the DBOS library.
47
+ Otherwise fallback to the same SQLite Postgres URL than the DBOS library.
47
48
  Note that for the latter to be possible, a configuration file must have been found, with an application name set.
48
49
  """
49
- database_url = db_url
50
- _app_db_name = None
51
- if database_url is None:
50
+ if os.environ.get("DBOS__CLOUD") == "true":
51
+ system_database_url = os.environ.get("DBOS_SYSTEM_DATABASE_URL")
52
+ application_database_url = os.environ.get("DBOS_DATABASE_URL")
53
+ assert system_database_url and application_database_url
54
+ return system_database_url, application_database_url
55
+ if system_database_url or application_database_url:
56
+ cfg: ConfigFile = {
57
+ "system_database_url": system_database_url,
58
+ "database_url": application_database_url,
59
+ }
60
+ return get_system_database_url(cfg), get_application_database_url(cfg)
61
+ else:
52
62
  # Load from config file if present
53
63
  try:
54
- config = load_config(run_process_config=False, silent=True)
55
- database_url = config.get("database_url")
56
- _app_db_name = _app_name_to_db_name(config["name"])
64
+ config = load_config(silent=True)
65
+ if config.get("database_url") or config.get("system_database_url"):
66
+ return get_system_database_url(config), get_application_database_url(
67
+ config
68
+ )
69
+ else:
70
+ _app_db_name = _app_name_to_db_name(config["name"])
71
+ # Fallback on the same defaults than the DBOS library
72
+ default_url = f"sqlite:///{_app_db_name}.sqlite"
73
+ return default_url, default_url
57
74
  except (FileNotFoundError, OSError):
58
- # Config file doesn't exist, continue with other fallbacks
59
- pass
60
- if database_url is None:
61
- database_url = os.getenv("DBOS_DATABASE_URL")
62
- if database_url is None and _app_db_name is not None:
63
- # Fallback on the same defaults than the DBOS library
64
- _password = os.environ.get("PGPASSWORD", "dbos")
65
- database_url = f"postgres://postgres:{_password}@localhost:5432/{_app_db_name}?connect_timeout=10&sslmode=prefer"
66
- if database_url is None:
67
- raise ValueError(
68
- "Missing database URL: please set it using the --db-url flag, the DBOS_DATABASE_URL environment variable, or in your dbos-config.yaml file."
69
- )
70
- assert is_valid_database_url(database_url)
71
- return database_url
72
-
73
-
74
- def start_client(db_url: Optional[str] = None) -> DBOSClient:
75
- database_url = _get_db_url(db_url)
76
- return DBOSClient(database_url=database_url)
75
+ typer.echo(
76
+ f"Error: Missing database URL: please set it using CLI flags or your dbos-config.yaml file.",
77
+ err=True,
78
+ )
79
+ raise typer.Exit(code=1)
77
80
 
78
81
 
79
82
  app = typer.Typer()
@@ -115,7 +118,7 @@ def _on_windows() -> bool:
115
118
  help="Start your DBOS application using the start commands in 'dbos-config.yaml'"
116
119
  )
117
120
  def start() -> None:
118
- config = load_config(run_process_config=False, silent=True)
121
+ config = load_config(silent=True)
119
122
  start_commands = config["runtimeConfig"]["start"]
120
123
  typer.echo("Executing start commands from 'dbos-config.yaml'")
121
124
  for command in start_commands:
@@ -264,7 +267,7 @@ def _resolve_project_name_and_template(
264
267
 
265
268
  @app.command(help="Create DBOS system tables.")
266
269
  def migrate(
267
- app_database_url: Annotated[
270
+ application_database_url: Annotated[
268
271
  typing.Optional[str],
269
272
  typer.Option(
270
273
  "--db-url",
@@ -289,28 +292,25 @@ def migrate(
289
292
  ),
290
293
  ] = None,
291
294
  ) -> None:
292
- app_database_url = _get_db_url(app_database_url)
293
- system_database_url = get_system_database_url(
294
- {
295
- "system_database_url": system_database_url,
296
- "database_url": app_database_url,
297
- "database": {},
298
- }
295
+ system_database_url, application_database_url = _get_db_url(
296
+ system_database_url=system_database_url,
297
+ application_database_url=application_database_url,
299
298
  )
300
299
 
301
300
  typer.echo(f"Starting DBOS migrations")
302
- typer.echo(f"Application database: {sa.make_url(app_database_url)}")
301
+ typer.echo(f"Application database: {sa.make_url(application_database_url)}")
303
302
  typer.echo(f"System database: {sa.make_url(system_database_url)}")
304
303
 
305
304
  # First, run DBOS migrations on the system database and the application database
306
305
  migrate_dbos_databases(
307
- app_database_url=app_database_url, system_database_url=system_database_url
306
+ app_database_url=application_database_url,
307
+ system_database_url=system_database_url,
308
308
  )
309
309
 
310
310
  # Next, assign permissions on the DBOS schema to the application role, if any
311
311
  if application_role:
312
312
  grant_dbos_schema_permissions(
313
- database_url=app_database_url, role_name=application_role
313
+ database_url=application_database_url, role_name=application_role
314
314
  )
315
315
  grant_dbos_schema_permissions(
316
316
  database_url=system_database_url, role_name=application_role
@@ -318,7 +318,7 @@ def migrate(
318
318
 
319
319
  # Next, run any custom migration commands specified in the configuration
320
320
  if os.path.exists("dbos-config.yaml"):
321
- config = load_config(run_process_config=False, silent=True)
321
+ config = load_config(silent=True)
322
322
  if "database" not in config:
323
323
  config["database"] = {}
324
324
  migrate_commands = (
@@ -346,20 +346,20 @@ def migrate(
346
346
  @app.command(help="Reset the DBOS system database")
347
347
  def reset(
348
348
  yes: bool = typer.Option(False, "-y", "--yes", help="Skip confirmation prompt"),
349
- sys_db_name: Annotated[
349
+ application_database_url: Annotated[
350
350
  typing.Optional[str],
351
351
  typer.Option(
352
- "--sys-db-name",
353
- "-s",
354
- help="Specify the name of the system database to reset",
352
+ "--db-url",
353
+ "-D",
354
+ help="Your DBOS application database URL",
355
355
  ),
356
356
  ] = None,
357
- db_url: Annotated[
357
+ system_database_url: Annotated[
358
358
  typing.Optional[str],
359
359
  typer.Option(
360
- "--db-url",
361
- "-D",
362
- help="Your DBOS application database URL",
360
+ "--sys-db-url",
361
+ "-s",
362
+ help="Your DBOS system database URL",
363
363
  ),
364
364
  ] = None,
365
365
  ) -> None:
@@ -371,9 +371,9 @@ def reset(
371
371
  typer.echo("Operation cancelled.")
372
372
  raise typer.Exit()
373
373
  try:
374
- database_url = _get_db_url(db_url)
375
- system_database_url = get_system_database_url(
376
- {"database_url": database_url, "database": {"sys_db_name": sys_db_name}}
374
+ system_database_url, application_database_url = _get_db_url(
375
+ system_database_url=system_database_url,
376
+ application_database_url=application_database_url,
377
377
  )
378
378
  SystemDatabase.reset_system_database(system_database_url)
379
379
  except Exception as e:
@@ -399,7 +399,7 @@ def debug(
399
399
 
400
400
  @workflow.command(help="List workflows for your application")
401
401
  def list(
402
- db_url: Annotated[
402
+ application_database_url: Annotated[
403
403
  typing.Optional[str],
404
404
  typer.Option(
405
405
  "--db-url",
@@ -407,6 +407,14 @@ def list(
407
407
  help="Your DBOS application database URL",
408
408
  ),
409
409
  ] = None,
410
+ system_database_url: Annotated[
411
+ typing.Optional[str],
412
+ typer.Option(
413
+ "--sys-db-url",
414
+ "-s",
415
+ help="Your DBOS system database URL",
416
+ ),
417
+ ] = None,
410
418
  limit: Annotated[
411
419
  int,
412
420
  typer.Option("--limit", "-l", help="Limit the results returned"),
@@ -419,7 +427,7 @@ def list(
419
427
  typing.Optional[str],
420
428
  typer.Option(
421
429
  "--start-time",
422
- "-s",
430
+ "-t",
423
431
  help="Retrieve workflows starting after this timestamp (ISO 8601 format)",
424
432
  ),
425
433
  ] = None,
@@ -472,7 +480,15 @@ def list(
472
480
  ),
473
481
  ] = None,
474
482
  ) -> None:
475
- workflows = start_client(db_url=db_url).list_workflows(
483
+ system_database_url, application_database_url = _get_db_url(
484
+ system_database_url=system_database_url,
485
+ application_database_url=application_database_url,
486
+ )
487
+ client = DBOSClient(
488
+ application_database_url=application_database_url,
489
+ system_database_url=system_database_url,
490
+ )
491
+ workflows = client.list_workflows(
476
492
  limit=limit,
477
493
  offset=offset,
478
494
  sort_desc=sort_desc,
@@ -489,7 +505,7 @@ def list(
489
505
  @workflow.command(help="Retrieve the status of a workflow")
490
506
  def get(
491
507
  workflow_id: Annotated[str, typer.Argument()],
492
- db_url: Annotated[
508
+ application_database_url: Annotated[
493
509
  typing.Optional[str],
494
510
  typer.Option(
495
511
  "--db-url",
@@ -497,19 +513,31 @@ def get(
497
513
  help="Your DBOS application database URL",
498
514
  ),
499
515
  ] = None,
516
+ system_database_url: Annotated[
517
+ typing.Optional[str],
518
+ typer.Option(
519
+ "--sys-db-url",
520
+ "-s",
521
+ help="Your DBOS system database URL",
522
+ ),
523
+ ] = None,
500
524
  ) -> None:
501
- status = (
502
- start_client(db_url=db_url)
503
- .retrieve_workflow(workflow_id=workflow_id)
504
- .get_status()
525
+ system_database_url, application_database_url = _get_db_url(
526
+ system_database_url=system_database_url,
527
+ application_database_url=application_database_url,
505
528
  )
529
+ client = DBOSClient(
530
+ application_database_url=application_database_url,
531
+ system_database_url=system_database_url,
532
+ )
533
+ status = client.retrieve_workflow(workflow_id=workflow_id).get_status()
506
534
  print(jsonpickle.encode(status, unpicklable=False))
507
535
 
508
536
 
509
537
  @workflow.command(help="List the steps of a workflow")
510
538
  def steps(
511
539
  workflow_id: Annotated[str, typer.Argument()],
512
- db_url: Annotated[
540
+ application_database_url: Annotated[
513
541
  typing.Optional[str],
514
542
  typer.Option(
515
543
  "--db-url",
@@ -517,10 +545,26 @@ def steps(
517
545
  help="Your DBOS application database URL",
518
546
  ),
519
547
  ] = None,
548
+ system_database_url: Annotated[
549
+ typing.Optional[str],
550
+ typer.Option(
551
+ "--sys-db-url",
552
+ "-s",
553
+ help="Your DBOS system database URL",
554
+ ),
555
+ ] = None,
520
556
  ) -> None:
557
+ system_database_url, application_database_url = _get_db_url(
558
+ system_database_url=system_database_url,
559
+ application_database_url=application_database_url,
560
+ )
561
+ client = DBOSClient(
562
+ application_database_url=application_database_url,
563
+ system_database_url=system_database_url,
564
+ )
521
565
  print(
522
566
  jsonpickle.encode(
523
- start_client(db_url=db_url).list_workflow_steps(workflow_id=workflow_id),
567
+ client.list_workflow_steps(workflow_id=workflow_id),
524
568
  unpicklable=False,
525
569
  )
526
570
  )
@@ -531,7 +575,7 @@ def steps(
531
575
  )
532
576
  def cancel(
533
577
  workflow_id: Annotated[str, typer.Argument()],
534
- db_url: Annotated[
578
+ application_database_url: Annotated[
535
579
  typing.Optional[str],
536
580
  typer.Option(
537
581
  "--db-url",
@@ -539,14 +583,30 @@ def cancel(
539
583
  help="Your DBOS application database URL",
540
584
  ),
541
585
  ] = None,
586
+ system_database_url: Annotated[
587
+ typing.Optional[str],
588
+ typer.Option(
589
+ "--sys-db-url",
590
+ "-s",
591
+ help="Your DBOS system database URL",
592
+ ),
593
+ ] = None,
542
594
  ) -> None:
543
- start_client(db_url=db_url).cancel_workflow(workflow_id=workflow_id)
595
+ system_database_url, application_database_url = _get_db_url(
596
+ system_database_url=system_database_url,
597
+ application_database_url=application_database_url,
598
+ )
599
+ client = DBOSClient(
600
+ application_database_url=application_database_url,
601
+ system_database_url=system_database_url,
602
+ )
603
+ client.cancel_workflow(workflow_id=workflow_id)
544
604
 
545
605
 
546
606
  @workflow.command(help="Resume a workflow that has been cancelled")
547
607
  def resume(
548
608
  workflow_id: Annotated[str, typer.Argument()],
549
- db_url: Annotated[
609
+ application_database_url: Annotated[
550
610
  typing.Optional[str],
551
611
  typer.Option(
552
612
  "--db-url",
@@ -554,8 +614,24 @@ def resume(
554
614
  help="Your DBOS application database URL",
555
615
  ),
556
616
  ] = None,
617
+ system_database_url: Annotated[
618
+ typing.Optional[str],
619
+ typer.Option(
620
+ "--sys-db-url",
621
+ "-s",
622
+ help="Your DBOS system database URL",
623
+ ),
624
+ ] = None,
557
625
  ) -> None:
558
- start_client(db_url=db_url).resume_workflow(workflow_id=workflow_id)
626
+ system_database_url, application_database_url = _get_db_url(
627
+ system_database_url=system_database_url,
628
+ application_database_url=application_database_url,
629
+ )
630
+ client = DBOSClient(
631
+ application_database_url=application_database_url,
632
+ system_database_url=system_database_url,
633
+ )
634
+ client.resume_workflow(workflow_id=workflow_id)
559
635
 
560
636
 
561
637
  @workflow.command(
@@ -563,7 +639,7 @@ def resume(
563
639
  )
564
640
  def restart(
565
641
  workflow_id: Annotated[str, typer.Argument()],
566
- db_url: Annotated[
642
+ application_database_url: Annotated[
567
643
  typing.Optional[str],
568
644
  typer.Option(
569
645
  "--db-url",
@@ -571,12 +647,24 @@ def restart(
571
647
  help="Your DBOS application database URL",
572
648
  ),
573
649
  ] = None,
650
+ system_database_url: Annotated[
651
+ typing.Optional[str],
652
+ typer.Option(
653
+ "--sys-db-url",
654
+ "-s",
655
+ help="Your DBOS system database URL",
656
+ ),
657
+ ] = None,
574
658
  ) -> None:
575
- status = (
576
- start_client(db_url=db_url)
577
- .fork_workflow(workflow_id=workflow_id, start_step=1)
578
- .get_status()
659
+ system_database_url, application_database_url = _get_db_url(
660
+ system_database_url=system_database_url,
661
+ application_database_url=application_database_url,
579
662
  )
663
+ client = DBOSClient(
664
+ application_database_url=application_database_url,
665
+ system_database_url=system_database_url,
666
+ )
667
+ status = client.fork_workflow(workflow_id=workflow_id, start_step=1).get_status()
580
668
  print(jsonpickle.encode(status, unpicklable=False))
581
669
 
582
670
 
@@ -589,7 +677,7 @@ def fork(
589
677
  int,
590
678
  typer.Option(
591
679
  "--step",
592
- "-s",
680
+ "-S",
593
681
  help="Restart from this step",
594
682
  ),
595
683
  ] = 1,
@@ -609,7 +697,7 @@ def fork(
609
697
  help="Custom application version for the forked workflow",
610
698
  ),
611
699
  ] = None,
612
- db_url: Annotated[
700
+ application_database_url: Annotated[
613
701
  typing.Optional[str],
614
702
  typer.Option(
615
703
  "--db-url",
@@ -617,8 +705,23 @@ def fork(
617
705
  help="Your DBOS application database URL",
618
706
  ),
619
707
  ] = None,
708
+ system_database_url: Annotated[
709
+ typing.Optional[str],
710
+ typer.Option(
711
+ "--sys-db-url",
712
+ "-s",
713
+ help="Your DBOS system database URL",
714
+ ),
715
+ ] = None,
620
716
  ) -> None:
621
- client = start_client(db_url=db_url)
717
+ system_database_url, application_database_url = _get_db_url(
718
+ system_database_url=system_database_url,
719
+ application_database_url=application_database_url,
720
+ )
721
+ client = DBOSClient(
722
+ application_database_url=application_database_url,
723
+ system_database_url=system_database_url,
724
+ )
622
725
 
623
726
  if forked_workflow_id is not None:
624
727
  with SetWorkflowID(forked_workflow_id):
@@ -638,7 +741,7 @@ def fork(
638
741
 
639
742
  @queue.command(name="list", help="List enqueued functions for your application")
640
743
  def list_queue(
641
- db_url: Annotated[
744
+ application_database_url: Annotated[
642
745
  typing.Optional[str],
643
746
  typer.Option(
644
747
  "--db-url",
@@ -646,6 +749,14 @@ def list_queue(
646
749
  help="Your DBOS application database URL",
647
750
  ),
648
751
  ] = None,
752
+ system_database_url: Annotated[
753
+ typing.Optional[str],
754
+ typer.Option(
755
+ "--sys-db-url",
756
+ "-s",
757
+ help="Your DBOS system database URL",
758
+ ),
759
+ ] = None,
649
760
  limit: Annotated[
650
761
  typing.Optional[int],
651
762
  typer.Option("--limit", "-l", help="Limit the results returned"),
@@ -654,7 +765,7 @@ def list_queue(
654
765
  typing.Optional[str],
655
766
  typer.Option(
656
767
  "--start-time",
657
- "-s",
768
+ "-t",
658
769
  help="Retrieve functions starting after this timestamp (ISO 8601 format)",
659
770
  ),
660
771
  ] = None,
@@ -707,7 +818,15 @@ def list_queue(
707
818
  ),
708
819
  ] = None,
709
820
  ) -> None:
710
- workflows = start_client(db_url=db_url).list_queued_workflows(
821
+ system_database_url, application_database_url = _get_db_url(
822
+ system_database_url=system_database_url,
823
+ application_database_url=application_database_url,
824
+ )
825
+ client = DBOSClient(
826
+ application_database_url=application_database_url,
827
+ system_database_url=system_database_url,
828
+ )
829
+ workflows = client.list_queued_workflows(
711
830
  limit=limit,
712
831
  offset=offset,
713
832
  sort_desc=sort_desc,
@@ -19,6 +19,10 @@
19
19
  "type": ["string", "null"],
20
20
  "description": "The URL of the application database"
21
21
  },
22
+ "system_database_url": {
23
+ "type": ["string", "null"],
24
+ "description": "The URL of the system database"
25
+ },
22
26
  "database": {
23
27
  "type": "object",
24
28
  "additionalProperties": false,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 1.13.0a5
3
+ Version: 1.13.0a7
4
4
  Summary: Ultra-lightweight durable execution in Python
5
5
  Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
6
  License: MIT
@@ -1,7 +1,7 @@
1
- dbos-1.13.0a5.dist-info/METADATA,sha256=obXcr7i8Wu_nO0bUihx40pr-fopo32nU3rqFBBe3D0o,13268
2
- dbos-1.13.0a5.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- dbos-1.13.0a5.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
- dbos-1.13.0a5.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
1
+ dbos-1.13.0a7.dist-info/METADATA,sha256=cqQQNrFsEmPBW7VJC40n6ieoNOd2Amm3CbDsM_Og2is,13268
2
+ dbos-1.13.0a7.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
+ dbos-1.13.0a7.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
+ dbos-1.13.0a7.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
5
5
  dbos/__init__.py,sha256=NssPCubaBxdiKarOWa-wViz1hdJSkmBGcpLX_gQ4NeA,891
6
6
  dbos/__main__.py,sha256=G7Exn-MhGrVJVDbgNlpzhfh8WMX_72t3_oJaFT9Lmt8,653
7
7
  dbos/_admin_server.py,sha256=e8ELhcDWqR3_PNobnNgUvLGh5lzZq0yFSF6dvtzoQRI,16267
@@ -22,16 +22,16 @@ dbos/_alembic_migrations/versions/d76646551a6c_workflow_queue.py,sha256=G942noph
22
22
  dbos/_alembic_migrations/versions/d994145b47b6_consolidate_inputs.py,sha256=_J0jP247fuo66fzOmLlKFO9FJ_CRBXlqa2lnLrcXugQ,672
23
23
  dbos/_alembic_migrations/versions/eab0cc1d9a14_job_queue.py,sha256=uvhFOtqbBreCePhAxZfIT0qCAI7BiZTou9wt6QnbY7c,1412
24
24
  dbos/_alembic_migrations/versions/f4b9b32ba814_functionname_childid_op_outputs.py,sha256=m90Lc5YH0ZISSq1MyxND6oq3RZrZKrIqEsZtwJ1jWxA,1049
25
- dbos/_app_db.py,sha256=e8mASnDX_tyE9DWf_yAZgIi7ZWeyVWWTrhCZK_Jy50g,16190
25
+ dbos/_app_db.py,sha256=GsV-uYU0QsChWwQDxnrh8_iiZ_zMQB-bsP2jPGIe2aM,16094
26
26
  dbos/_classproperty.py,sha256=f0X-_BySzn3yFDRKB2JpCbLYQ9tLwt1XftfshvY7CBs,626
27
- dbos/_client.py,sha256=hSSIqWZEbGVAyRy80rS4Sywaf_biQOF17ThW3Eyaaso,18267
27
+ dbos/_client.py,sha256=n6Wk_8sG5qtqJw3vAkBTh4qsl7q_t6nnRukGjTJbwqg,18794
28
28
  dbos/_conductor/conductor.py,sha256=3E_hL3c9g9yWqKZkvI6KA0-ZzPMPRo06TOzT1esMiek,24114
29
29
  dbos/_conductor/protocol.py,sha256=q3rgLxINFtWFigdOONc-4gX4vn66UmMlJQD6Kj8LnL4,7420
30
30
  dbos/_context.py,sha256=IMboNgbCqTxfIORqeifE3da-Ce5siMz7MYMLPk5M-AQ,26851
31
31
  dbos/_core.py,sha256=2IWEkewiYL3d3MrhMfqj0JDWNyNM54rpW7CRGjBTPfk,48788
32
32
  dbos/_croniter.py,sha256=XHAyUyibs_59sJQfSNWkP7rqQY6_XrlfuuCxk4jYqek,47559
33
33
  dbos/_dbos.py,sha256=wKLN7W1ej6cyEOHnCtt3-awnU6SR6MQAlOvTTt5_N-E,58219
34
- dbos/_dbos_config.py,sha256=jv-k2WyXgfoR3R0NaPxAFx5OzZYjr0rjH2npsbokGRM,22321
34
+ dbos/_dbos_config.py,sha256=_26ktif8qAZW4Ujg6dZfLkYO7dE4CI8b3IQbw_5YkpA,25710
35
35
  dbos/_debug.py,sha256=99j2SChWmCPAlZoDmjsJGe77tpU2LEa8E2TtLAnnh7o,1831
36
36
  dbos/_docker_pg_helper.py,sha256=tLJXWqZ4S-ExcaPnxg_i6cVxL6ZxrYlZjaGsklY-s2I,6115
37
37
  dbos/_error.py,sha256=GwO0Ng4d4iB52brY09-Ss6Cz_V28Xc0D0cRCzZ6XmNM,8688
@@ -52,9 +52,9 @@ dbos/_schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  dbos/_schemas/application_database.py,sha256=SypAS9l9EsaBHFn9FR8jmnqt01M74d9AF1AMa4m2hhI,1040
53
53
  dbos/_schemas/system_database.py,sha256=-dAKk-_Y3vzbpLT4ei-sIrBQgFyQiwPj1enZb1TYc8I,4943
54
54
  dbos/_serialization.py,sha256=bWuwhXSQcGmiazvhJHA5gwhrRWxtmFmcCFQSDJnqqkU,3666
55
- dbos/_sys_db.py,sha256=zlAJ3YPLuzN8Ju32_lfhsq3-MxnH4V45Rf6X9Imxqf0,81838
55
+ dbos/_sys_db.py,sha256=DhpthOe2hbG7Cp8CxJd5tRUyqgKJ7HWbgEySpt6GTwY,81756
56
56
  dbos/_sys_db_postgres.py,sha256=WcG-f1CUzUNBGEOjqKEp6DDraN63jTnJ6CAfieCcxOs,7555
57
- dbos/_sys_db_sqlite.py,sha256=58Fv7paGloCmpXdWZVCEpcZFvHWLuEkw4XBKCWprGsA,7500
57
+ dbos/_sys_db_sqlite.py,sha256=xT9l-czMhLmfuu5UcnBzAyUxSFgzt3XtEWx9t_D8mZs,7361
58
58
  dbos/_templates/dbos-db-starter/README.md,sha256=GhxhBj42wjTt1fWEtwNriHbJuKb66Vzu89G4pxNHw2g,930
59
59
  dbos/_templates/dbos-db-starter/__package/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
60
  dbos/_templates/dbos-db-starter/__package/main.py.dbos,sha256=aQnBPSSQpkB8ERfhf7gB7P9tsU6OPKhZscfeh0yiaD8,2702
@@ -64,15 +64,14 @@ dbos/_templates/dbos-db-starter/dbos-config.yaml.dbos,sha256=0wPktElM7kMB3OPHTXw
64
64
  dbos/_templates/dbos-db-starter/migrations/env.py.dbos,sha256=IBB_gz9RjC20HPfOTGZzS6kTbv3jXhiOrnWpbJNk1Gk,2509
65
65
  dbos/_templates/dbos-db-starter/migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
66
66
  dbos/_templates/dbos-db-starter/migrations/versions/2024_07_31_180642_init.py,sha256=MpS7LGaJS0CpvsjhfDkp9EJqvMvVCjRPfUp4c0aE2ys,941
67
- dbos/_templates/dbos-db-starter/start_postgres_docker.py,sha256=lQVLlYO5YkhGPEgPqwGc7Y8uDKse9HsWv5fynJEFJHM,1681
68
67
  dbos/_tracer.py,sha256=8aOAVTBnj2q9DcOb5KJCfo56CVZ1ZvsWBscaNlIX-7k,3150
69
68
  dbos/_utils.py,sha256=ZdoM1MDbHnlJrh31zfhp3iX62bAxK1kyvMwXnltC_84,1779
70
69
  dbos/_workflow_commands.py,sha256=EmmAaQfRWeOZm_WPTznuU-O3he3jiSzzT9VpYrhxugE,4835
71
70
  dbos/cli/_github_init.py,sha256=Y_bDF9gfO2jB1id4FV5h1oIxEJRWyqVjhb7bNEa5nQ0,3224
72
71
  dbos/cli/_template_init.py,sha256=7JBcpMqP1r2mfCnvWatu33z8ctEGHJarlZYKgB83cXE,2972
73
- dbos/cli/cli.py,sha256=basgruBuvOMIb5nrsa1cVKOOYvSx_Lqx3M51P0d6NEU,22698
72
+ dbos/cli/cli.py,sha256=ypaDSJq8HMDDiTsXqoxKw7B5n2wBT2ujjHjzkuh1AsY,26879
74
73
  dbos/cli/migration.py,sha256=5GiyagLZkyVvDz3StYxtFdkFoKFCmh6eSXjzsIGhZ_A,3330
75
- dbos/dbos-config.schema.json,sha256=CjaspeYmOkx6Ip_pcxtmfXJTn_YGdSx_0pcPBF7KZmo,6060
74
+ dbos/dbos-config.schema.json,sha256=LyUT1DOTaAwOP6suxQGS5KemVIqXGPyu_q7Hbo0neA8,6192
76
75
  dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
77
76
  version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
78
- dbos-1.13.0a5.dist-info/RECORD,,
77
+ dbos-1.13.0a7.dist-info/RECORD,,
@@ -1,67 +0,0 @@
1
- import os
2
- import subprocess
3
- import sys
4
- import time
5
-
6
- # Default PostgreSQL port
7
- port = "5432"
8
-
9
- # Set the host PostgreSQL port with the -p/--port flag
10
- for i, arg in enumerate(sys.argv):
11
- if arg in ["-p", "--port"]:
12
- if i + 1 < len(sys.argv):
13
- port = sys.argv[i + 1]
14
-
15
- if "PGPASSWORD" not in os.environ:
16
- print("Error: PGPASSWORD is not set.")
17
- sys.exit(1)
18
-
19
- try:
20
- subprocess.run(
21
- [
22
- "docker",
23
- "run",
24
- "--rm",
25
- "--name=dbos-db",
26
- f'--env=POSTGRES_PASSWORD={os.environ["PGPASSWORD"]}',
27
- "--env=PGDATA=/var/lib/postgresql/data",
28
- "--volume=/var/lib/postgresql/data",
29
- "-p",
30
- f"{port}:5432",
31
- "-d",
32
- "pgvector/pgvector:pg16",
33
- ],
34
- check=True,
35
- )
36
-
37
- print("Waiting for PostgreSQL to start...")
38
- attempts = 30
39
-
40
- while attempts > 0:
41
- try:
42
- subprocess.run(
43
- [
44
- "docker",
45
- "exec",
46
- "dbos-db",
47
- "psql",
48
- "-U",
49
- "postgres",
50
- "-c",
51
- "SELECT 1;",
52
- ],
53
- check=True,
54
- capture_output=True,
55
- )
56
- print("PostgreSQL started!")
57
- print("Database started successfully!")
58
- break
59
- except subprocess.CalledProcessError:
60
- attempts -= 1
61
- time.sleep(1)
62
-
63
- if attempts == 0:
64
- print("Failed to start PostgreSQL.")
65
-
66
- except subprocess.CalledProcessError as error:
67
- print(f"Error starting PostgreSQL in Docker: {error}")