dbos 0.5.0a3__tar.gz → 0.5.0a5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (62) hide show
  1. {dbos-0.5.0a3 → dbos-0.5.0a5}/PKG-INFO +1 -1
  2. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/application_database.py +9 -4
  3. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/context.py +16 -18
  4. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/core.py +41 -55
  5. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/dbos.py +14 -17
  6. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/error.py +5 -5
  7. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/registrations.py +1 -1
  8. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/system_database.py +50 -22
  9. {dbos-0.5.0a3 → dbos-0.5.0a5}/pyproject.toml +1 -1
  10. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/classdefs.py +10 -10
  11. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_admin_server.py +6 -6
  12. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_classdecorators.py +22 -22
  13. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_concurrency.py +33 -20
  14. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_dbos.py +54 -50
  15. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_fastapi.py +6 -6
  16. {dbos-0.5.0a3 → dbos-0.5.0a5}/LICENSE +0 -0
  17. {dbos-0.5.0a3 → dbos-0.5.0a5}/README.md +0 -0
  18. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/__init__.py +0 -0
  19. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/admin_sever.py +0 -0
  20. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/cli.py +0 -0
  21. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/dbos-config.schema.json +0 -0
  22. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/dbos_config.py +0 -0
  23. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/decorators.py +0 -0
  24. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/fastapi.py +0 -0
  25. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/logger.py +0 -0
  26. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/migrations/env.py +0 -0
  27. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/migrations/script.py.mako +0 -0
  28. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/migrations/versions/5c361fc04708_added_system_tables.py +0 -0
  29. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/migrations/versions/a3b18ad34abe_added_triggers.py +0 -0
  30. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/py.typed +0 -0
  31. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/recovery.py +0 -0
  32. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/roles.py +0 -0
  33. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/scheduler/croniter.py +0 -0
  34. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/scheduler/scheduler.py +0 -0
  35. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/schemas/__init__.py +0 -0
  36. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/schemas/application_database.py +0 -0
  37. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/schemas/system_database.py +0 -0
  38. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/README.md +0 -0
  39. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/__package/__init__.py +0 -0
  40. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/__package/main.py +0 -0
  41. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/__package/schema.py +0 -0
  42. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/alembic.ini +0 -0
  43. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/dbos-config.yaml.dbos +0 -0
  44. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/migrations/env.py.dbos +0 -0
  45. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/migrations/script.py.mako +0 -0
  46. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/migrations/versions/2024_07_31_180642_init.py +0 -0
  47. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/templates/hello/start_postgres_docker.py +0 -0
  48. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/tracer.py +0 -0
  49. {dbos-0.5.0a3 → dbos-0.5.0a5}/dbos/utils.py +0 -0
  50. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/__init__.py +0 -0
  51. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/atexit_no_ctor.py +0 -0
  52. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/atexit_no_launch.py +0 -0
  53. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/conftest.py +0 -0
  54. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/more_classdefs.py +0 -0
  55. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/scheduler/test_croniter.py +0 -0
  56. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/scheduler/test_scheduler.py +0 -0
  57. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_config.py +0 -0
  58. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_failures.py +0 -0
  59. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_package.py +0 -0
  60. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_schema_migration.py +0 -0
  61. {dbos-0.5.0a3 → dbos-0.5.0a5}/tests/test_singleton.py +0 -0
  62. {dbos-0.5.0a3 → dbos-0.5.0a5}/version/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 0.5.0a3
3
+ Version: 0.5.0a5
4
4
  Summary: A Python framework for backends that scale
5
5
  Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
6
  License: MIT
@@ -3,6 +3,7 @@ from typing import Optional, TypedDict, cast
3
3
  import sqlalchemy as sa
4
4
  import sqlalchemy.dialects.postgresql as pg
5
5
  import sqlalchemy.exc as sa_exc
6
+ from sqlalchemy.exc import DBAPIError
6
7
  from sqlalchemy.orm import Session, sessionmaker
7
8
 
8
9
  from dbos.error import DBOSWorkflowConflictIDError
@@ -95,8 +96,10 @@ class ApplicationDatabase:
95
96
  ),
96
97
  )
97
98
  )
98
- except sa_exc.IntegrityError:
99
- raise DBOSWorkflowConflictIDError(output["workflow_uuid"])
99
+ except DBAPIError as dbapi_error:
100
+ if dbapi_error.orig.pgcode == "23505": # type: ignore
101
+ raise DBOSWorkflowConflictIDError(output["workflow_uuid"])
102
+ raise dbapi_error
100
103
  except Exception as e:
101
104
  raise e
102
105
 
@@ -118,8 +121,10 @@ class ApplicationDatabase:
118
121
  ),
119
122
  )
120
123
  )
121
- except sa_exc.IntegrityError:
122
- raise DBOSWorkflowConflictIDError(output["workflow_uuid"])
124
+ except DBAPIError as dbapi_error:
125
+ if dbapi_error.orig.pgcode == "23505": # type: ignore
126
+ raise DBOSWorkflowConflictIDError(output["workflow_uuid"])
127
+ raise dbapi_error
123
128
  except Exception as e:
124
129
  raise e
125
130
 
@@ -18,18 +18,16 @@ from .logger import dbos_logger
18
18
  from .tracer import dbos_tracer
19
19
 
20
20
 
21
- # Values must be the same as in TypeScript Transact
21
+ # These are used to tag OTel traces
22
22
  class OperationType(Enum):
23
23
  HANDLER = "handler"
24
24
  WORKFLOW = "workflow"
25
25
  TRANSACTION = "transaction"
26
- COMMUNICATOR = "communicator"
26
+ STEP = "step"
27
27
  PROCEDURE = "procedure"
28
28
 
29
29
 
30
- OperationTypes = Literal[
31
- "handler", "workflow", "transaction", "communicator", "procedure"
32
- ]
30
+ OperationTypes = Literal["handler", "workflow", "transaction", "step", "procedure"]
33
31
 
34
32
 
35
33
  # Keys must be the same as in TypeScript Transact
@@ -64,7 +62,7 @@ class DBOSContext:
64
62
  self.function_id: int = -1
65
63
  self.in_recovery: bool = False
66
64
 
67
- self.curr_comm_function_id: int = -1
65
+ self.curr_step_function_id: int = -1
68
66
  self.curr_tx_function_id: int = -1
69
67
  self.sql_session: Optional[Session] = None
70
68
  self.spans: list[Span] = []
@@ -117,26 +115,26 @@ class DBOSContext:
117
115
  def is_workflow(self) -> bool:
118
116
  return (
119
117
  len(self.workflow_id) > 0
120
- and not self.is_communicator()
118
+ and not self.is_step()
121
119
  and not self.is_transaction()
122
120
  )
123
121
 
124
122
  def is_transaction(self) -> bool:
125
123
  return self.sql_session is not None
126
124
 
127
- def is_communicator(self) -> bool:
128
- return self.curr_comm_function_id >= 0
125
+ def is_step(self) -> bool:
126
+ return self.curr_step_function_id >= 0
129
127
 
130
- def start_communicator(
128
+ def start_step(
131
129
  self,
132
130
  fid: int,
133
131
  attributes: TracedAttributes,
134
132
  ) -> None:
135
- self.curr_comm_function_id = fid
133
+ self.curr_step_function_id = fid
136
134
  self._start_span(attributes)
137
135
 
138
- def end_communicator(self, exc_value: Optional[BaseException]) -> None:
139
- self.curr_comm_function_id = -1
136
+ def end_step(self, exc_value: Optional[BaseException]) -> None:
137
+ self.curr_step_function_id = -1
140
138
  self._end_span(exc_value)
141
139
 
142
140
  def start_transaction(
@@ -375,7 +373,7 @@ class EnterDBOSChildWorkflow:
375
373
  def __enter__(self) -> DBOSContext:
376
374
  ctx = assert_current_dbos_context()
377
375
  self.parent_ctx = ctx
378
- assert ctx.is_workflow() # Is in a workflow and not in tx/comm
376
+ assert ctx.is_workflow() # Is in a workflow and not in a step
379
377
  ctx.function_id += 1
380
378
  if len(ctx.id_assigned_for_next_workflow) == 0:
381
379
  ctx.id_assigned_for_next_workflow = (
@@ -401,7 +399,7 @@ class EnterDBOSChildWorkflow:
401
399
  return False # Did not handle
402
400
 
403
401
 
404
- class EnterDBOSCommunicator:
402
+ class EnterDBOSStep:
405
403
  def __init__(
406
404
  self,
407
405
  attributes: TracedAttributes,
@@ -412,7 +410,7 @@ class EnterDBOSCommunicator:
412
410
  ctx = assert_current_dbos_context()
413
411
  assert ctx.is_workflow()
414
412
  ctx.function_id += 1
415
- ctx.start_communicator(ctx.function_id, attributes=self.attributes)
413
+ ctx.start_step(ctx.function_id, attributes=self.attributes)
416
414
  return ctx
417
415
 
418
416
  def __exit__(
@@ -422,8 +420,8 @@ class EnterDBOSCommunicator:
422
420
  traceback: Optional[TracebackType],
423
421
  ) -> Literal[False]:
424
422
  ctx = assert_current_dbos_context()
425
- assert ctx.is_communicator()
426
- ctx.end_communicator(exc_value)
423
+ assert ctx.is_step()
424
+ ctx.end_step(exc_value)
427
425
  return False # Did not handle
428
426
 
429
427
 
@@ -19,20 +19,18 @@ from dbos.context import (
19
19
  DBOSContextEnsure,
20
20
  DBOSContextSwap,
21
21
  EnterDBOSChildWorkflow,
22
- EnterDBOSCommunicator,
22
+ EnterDBOSStep,
23
23
  EnterDBOSTransaction,
24
24
  EnterDBOSWorkflow,
25
25
  OperationType,
26
26
  SetWorkflowID,
27
27
  TracedAttributes,
28
28
  assert_current_dbos_context,
29
- clear_local_dbos_context,
30
29
  get_local_dbos_context,
31
- set_local_dbos_context,
32
30
  )
33
31
  from dbos.error import (
34
- DBOSCommunicatorMaxRetriesExceededError,
35
32
  DBOSException,
33
+ DBOSMaxStepRetriesExceeded,
36
34
  DBOSNonExistentWorkflowError,
37
35
  DBOSRecoveryError,
38
36
  DBOSWorkflowConflictIDError,
@@ -61,7 +59,6 @@ if TYPE_CHECKING:
61
59
  from dbos.dbos import IsolationLevel
62
60
 
63
61
  from sqlalchemy.exc import DBAPIError
64
- from sqlalchemy.orm import Session
65
62
 
66
63
  P = ParamSpec("P") # A generic type for workflow parameters
67
64
  R = TypeVar("R", covariant=True) # A generic type for workflow return values
@@ -139,14 +136,18 @@ def _init_workflow(
139
136
  "recovery_attempts": None,
140
137
  }
141
138
 
139
+ # If we have a class name, the first arg is the instance and do not serialize
140
+ if class_name is not None:
141
+ inputs = {"args": inputs["args"][1:], "kwargs": inputs["kwargs"]}
142
+
142
143
  if temp_wf_type != "transaction":
143
- # Don't synchronously record the status or inputs for single transaction workflows
144
+ # Synchronously record the status and inputs for workflows and single-step workflows
145
+ # We also have to do this for single-step workflows because of the foreign key constraint on the operation outputs table
144
146
  dbos.sys_db.update_workflow_status(status, False, ctx.in_recovery)
145
-
146
- # If we have a class name, the first arg is the instance and do not serialize
147
- if class_name is not None:
148
- inputs = {"args": inputs["args"][1:], "kwargs": inputs["kwargs"]}
149
147
  dbos.sys_db.update_workflow_inputs(wfid, utils.serialize(inputs))
148
+ else:
149
+ # Buffer the inputs for single-transaction workflows, but don't buffer the status
150
+ dbos.sys_db.buffer_workflow_inputs(wfid, utils.serialize(inputs))
150
151
 
151
152
  return status
152
153
 
@@ -176,20 +177,6 @@ def _execute_workflow(
176
177
  status["error"] = utils.serialize(error)
177
178
  dbos.sys_db.update_workflow_status(status)
178
179
  raise error
179
- finally:
180
- if get_temp_workflow_type(func) == "transaction":
181
- # Buffer the inputs for single transaction workflows
182
- inputs: WorkflowInputs = {
183
- "args": args,
184
- "kwargs": kwargs,
185
- }
186
- # If we have a class name, the first arg is the instance and do not serialize
187
- class_name = get_dbos_class_name(get_func_info(func), func, args)
188
- if class_name is not None:
189
- inputs = {"args": inputs["args"][1:], "kwargs": inputs["kwargs"]}
190
- dbos.sys_db.buffer_workflow_inputs(
191
- status["workflow_uuid"], utils.serialize(inputs)
192
- )
193
180
 
194
181
  return output
195
182
 
@@ -362,7 +349,7 @@ def _start_workflow(
362
349
 
363
350
  # Sequence of events for starting a workflow:
364
351
  # First - is there a WF already running?
365
- # (and not in tx/comm as that is an error)
352
+ # (and not in step as that is an error)
366
353
  # Assign an ID to the workflow, if it doesn't have an app-assigned one
367
354
  # If this is a root workflow, assign a new ID
368
355
  # If this is a child workflow, assign parent wf id with call# suffix
@@ -370,7 +357,7 @@ def _start_workflow(
370
357
  # Pass the new context to a worker thread that will run the wf function
371
358
  cur_ctx = get_local_dbos_context()
372
359
  if cur_ctx is not None and cur_ctx.is_within_workflow():
373
- assert cur_ctx.is_workflow() # Not in tx / comm
360
+ assert cur_ctx.is_workflow() # Not in a step
374
361
  cur_ctx.function_id += 1
375
362
  if len(cur_ctx.id_assigned_for_next_workflow) == 0:
376
363
  cur_ctx.id_assigned_for_next_workflow = (
@@ -517,7 +504,7 @@ def _transaction(
517
504
  def wrapper(*args: Any, **kwargs: Any) -> Any:
518
505
  rr: Optional[str] = check_required_roles(func, fi)
519
506
  # Entering transaction is allowed:
520
- # In a workflow (that is not in a transaction / comm already)
507
+ # In a workflow (that is not in a step already)
521
508
  # Not in a workflow (we will start the single op workflow)
522
509
  ctx = get_local_dbos_context()
523
510
  if ctx and ctx.is_within_workflow():
@@ -544,7 +531,7 @@ def _transaction(
544
531
  return decorator
545
532
 
546
533
 
547
- def _communicator(
534
+ def _step(
548
535
  dbosreg: "_DBOSRegistry",
549
536
  *,
550
537
  retries_allowed: bool = False,
@@ -554,7 +541,7 @@ def _communicator(
554
541
  ) -> Callable[[F], F]:
555
542
  def decorator(func: F) -> F:
556
543
 
557
- def invoke_comm(*args: Any, **kwargs: Any) -> Any:
544
+ def invoke_step(*args: Any, **kwargs: Any) -> Any:
558
545
  if dbosreg.dbos is None:
559
546
  raise DBOSException(
560
547
  f"Function {func.__name__} invoked before DBOS initialized"
@@ -563,10 +550,10 @@ def _communicator(
563
550
 
564
551
  attributes: TracedAttributes = {
565
552
  "name": func.__name__,
566
- "operationType": OperationType.COMMUNICATOR.value,
553
+ "operationType": OperationType.STEP.value,
567
554
  }
568
- with EnterDBOSCommunicator(attributes) as ctx:
569
- comm_output: OperationResultInternal = {
555
+ with EnterDBOSStep(attributes) as ctx:
556
+ step_output: OperationResultInternal = {
570
557
  "workflow_uuid": ctx.workflow_id,
571
558
  "function_id": ctx.function_id,
572
559
  "output": None,
@@ -591,24 +578,24 @@ def _communicator(
591
578
  for attempt in range(1, local_max_attempts + 1):
592
579
  try:
593
580
  output = func(*args, **kwargs)
594
- comm_output["output"] = utils.serialize(output)
581
+ step_output["output"] = utils.serialize(output)
595
582
  error = None
596
583
  break
597
584
  except Exception as err:
598
585
  error = err
599
586
  if retries_allowed:
600
587
  dbos.logger.warning(
601
- f"Communicator being automatically retried. (attempt {attempt} of {local_max_attempts}). {traceback.format_exc()}"
588
+ f"Step being automatically retried. (attempt {attempt} of {local_max_attempts}). {traceback.format_exc()}"
602
589
  )
603
590
  ctx.get_current_span().add_event(
604
- f"Communicator attempt {attempt} failed",
591
+ f"Step attempt {attempt} failed",
605
592
  {
606
593
  "error": str(error),
607
594
  "retryIntervalSeconds": local_interval_seconds,
608
595
  },
609
596
  )
610
597
  if attempt == local_max_attempts:
611
- error = DBOSCommunicatorMaxRetriesExceededError()
598
+ error = DBOSMaxStepRetriesExceeded()
612
599
  else:
613
600
  time.sleep(local_interval_seconds)
614
601
  local_interval_seconds = min(
@@ -616,10 +603,11 @@ def _communicator(
616
603
  max_retry_interval_seconds,
617
604
  )
618
605
 
619
- comm_output["error"] = (
606
+ step_output["error"] = (
620
607
  utils.serialize(error) if error is not None else None
621
608
  )
622
- dbos.sys_db.record_operation_result(comm_output)
609
+ dbos.sys_db.record_operation_result(step_output)
610
+
623
611
  if error is not None:
624
612
  raise error
625
613
  return output
@@ -629,20 +617,18 @@ def _communicator(
629
617
  @wraps(func)
630
618
  def wrapper(*args: Any, **kwargs: Any) -> Any:
631
619
  rr: Optional[str] = check_required_roles(func, fi)
632
- # Entering communicator is allowed:
633
- # In a communicator already, just call the original function directly.
634
- # In a workflow (that is not in a transaction / comm already)
620
+ # Entering step is allowed:
621
+ # In a step already, just call the original function directly.
622
+ # In a workflow (that is not in a step already)
635
623
  # Not in a workflow (we will start the single op workflow)
636
624
  ctx = get_local_dbos_context()
637
- if ctx and ctx.is_communicator():
625
+ if ctx and ctx.is_step():
638
626
  # Call the original function directly
639
627
  return func(*args, **kwargs)
640
628
  if ctx and ctx.is_within_workflow():
641
- assert (
642
- ctx.is_workflow()
643
- ), "Communicators must be called from within workflows"
629
+ assert ctx.is_workflow(), "Steps must be called from within workflows"
644
630
  with DBOSAssumeRole(rr):
645
- return invoke_comm(*args, **kwargs)
631
+ return invoke_step(*args, **kwargs)
646
632
  else:
647
633
  tempwf = dbosreg.workflow_info_map.get("<temp>." + func.__qualname__)
648
634
  assert tempwf
@@ -653,7 +639,7 @@ def _communicator(
653
639
 
654
640
  wrapped_wf = _workflow_wrapper(dbosreg, temp_wf)
655
641
  set_dbos_func_name(temp_wf, "<temp>." + func.__qualname__)
656
- set_temp_workflow_type(temp_wf, "communicator")
642
+ set_temp_workflow_type(temp_wf, "step")
657
643
  dbosreg.register_wf_function(get_dbos_func_name(temp_wf), wrapped_wf)
658
644
 
659
645
  return cast(F, wrapper)
@@ -668,10 +654,10 @@ def _send(
668
654
  attributes: TracedAttributes = {
669
655
  "name": "send",
670
656
  }
671
- with EnterDBOSCommunicator(attributes) as ctx:
657
+ with EnterDBOSStep(attributes) as ctx:
672
658
  dbos.sys_db.send(
673
659
  ctx.workflow_id,
674
- ctx.curr_comm_function_id,
660
+ ctx.curr_step_function_id,
675
661
  destination_id,
676
662
  message,
677
663
  topic,
@@ -697,12 +683,12 @@ def _recv(
697
683
  attributes: TracedAttributes = {
698
684
  "name": "recv",
699
685
  }
700
- with EnterDBOSCommunicator(attributes) as ctx:
686
+ with EnterDBOSStep(attributes) as ctx:
701
687
  ctx.function_id += 1 # Reserve for the sleep
702
688
  timeout_function_id = ctx.function_id
703
689
  return dbos.sys_db.recv(
704
690
  ctx.workflow_id,
705
- ctx.curr_comm_function_id,
691
+ ctx.curr_step_function_id,
706
692
  timeout_function_id,
707
693
  topic,
708
694
  timeout_seconds,
@@ -722,9 +708,9 @@ def _set_event(dbos: "DBOS", key: str, value: Any) -> None:
722
708
  attributes: TracedAttributes = {
723
709
  "name": "set_event",
724
710
  }
725
- with EnterDBOSCommunicator(attributes) as ctx:
711
+ with EnterDBOSStep(attributes) as ctx:
726
712
  dbos.sys_db.set_event(
727
- ctx.workflow_id, ctx.curr_comm_function_id, key, value
713
+ ctx.workflow_id, ctx.curr_step_function_id, key, value
728
714
  )
729
715
  else:
730
716
  # Cannot call it from outside of a workflow
@@ -743,12 +729,12 @@ def _get_event(
743
729
  attributes: TracedAttributes = {
744
730
  "name": "get_event",
745
731
  }
746
- with EnterDBOSCommunicator(attributes) as ctx:
732
+ with EnterDBOSStep(attributes) as ctx:
747
733
  ctx.function_id += 1
748
734
  timeout_function_id = ctx.function_id
749
735
  caller_ctx: GetEventWorkflowContext = {
750
736
  "workflow_uuid": ctx.workflow_id,
751
- "function_id": ctx.curr_comm_function_id,
737
+ "function_id": ctx.curr_step_function_id,
752
738
  "timeout_function_id": timeout_function_id,
753
739
  }
754
740
  return dbos.sys_db.get_event(workflow_id, key, timeout_seconds, caller_ctx)
@@ -25,13 +25,13 @@ from opentelemetry.trace import Span
25
25
 
26
26
  from dbos.core import (
27
27
  TEMP_SEND_WF_NAME,
28
- _communicator,
29
28
  _execute_workflow_id,
30
29
  _get_event,
31
30
  _recv,
32
31
  _send,
33
32
  _set_event,
34
33
  _start_workflow,
34
+ _step,
35
35
  _transaction,
36
36
  _workflow,
37
37
  _workflow_wrapper,
@@ -63,7 +63,7 @@ else:
63
63
 
64
64
  from dbos.admin_sever import AdminServer
65
65
  from dbos.context import (
66
- EnterDBOSCommunicator,
66
+ EnterDBOSStep,
67
67
  TracedAttributes,
68
68
  assert_current_dbos_context,
69
69
  get_local_dbos_context,
@@ -179,7 +179,7 @@ class DBOS:
179
179
  Main access class for DBOS functionality.
180
180
 
181
181
  `DBOS` contains functions and properties for:
182
- 1. Decorating classes, workflows, transactions, and communicators
182
+ 1. Decorating classes, workflows, and steps
183
183
  2. Starting workflow functions
184
184
  3. Retrieving workflow status information
185
185
  4. Interacting with workflows via events and messages
@@ -388,9 +388,8 @@ class DBOS:
388
388
  """
389
389
  return _transaction(_get_or_create_dbos_registry(), isolation_level)
390
390
 
391
- # Mirror the CommunicatorConfig from TS. However, we disable retries by default.
392
391
  @classmethod
393
- def communicator(
392
+ def step(
394
393
  cls,
395
394
  *,
396
395
  retries_allowed: bool = False,
@@ -399,17 +398,17 @@ class DBOS:
399
398
  backoff_rate: float = 2.0,
400
399
  ) -> Callable[[F], F]:
401
400
  """
402
- Decorate and configure a function for use as a DBOS communicator.
401
+ Decorate and configure a function for use as a DBOS step.
403
402
 
404
403
  Args:
405
404
  retries_allowed(bool): If true, enable retries on thrown exceptions
406
405
  interval_seconds(float): Time between retry attempts
407
406
  backoff_rate(float): Multiplier for exponentially increasing `interval_seconds` between retries
408
- max_attempts(int): Maximum number of communicator retries before raising an exception
407
+ max_attempts(int): Maximum number of retries before raising an exception
409
408
 
410
409
  """
411
410
 
412
- return _communicator(
411
+ return _step(
413
412
  _get_or_create_dbos_registry(),
414
413
  retries_allowed=retries_allowed,
415
414
  interval_seconds=interval_seconds,
@@ -542,9 +541,9 @@ class DBOS:
542
541
  }
543
542
  if seconds <= 0:
544
543
  return
545
- with EnterDBOSCommunicator(attributes) as ctx:
544
+ with EnterDBOSStep(attributes) as ctx:
546
545
  _get_dbos_instance().sys_db.sleep(
547
- ctx.workflow_id, ctx.curr_comm_function_id, seconds
546
+ ctx.workflow_id, ctx.curr_step_function_id, seconds
548
547
  )
549
548
 
550
549
  @classmethod
@@ -615,9 +614,7 @@ class DBOS:
615
614
  def sql_session(cls) -> Session:
616
615
  """Return the SQLAlchemy `Session` for the current context, which must be within a transaction function."""
617
616
  ctx = assert_current_dbos_context()
618
- assert (
619
- ctx.is_transaction()
620
- ), "sql_session is only available within a transaction."
617
+ assert ctx.is_transaction(), "db is only available within a transaction."
621
618
  rv = ctx.sql_session
622
619
  assert rv
623
620
  return rv
@@ -628,7 +625,7 @@ class DBOS:
628
625
  ctx = assert_current_dbos_context()
629
626
  assert (
630
627
  ctx.is_within_workflow()
631
- ), "workflow_id is only available within a workflow, transaction, or communicator."
628
+ ), "workflow_id is only available within a DBOS operation."
632
629
  return ctx.workflow_id
633
630
 
634
631
  @classproperty
@@ -722,9 +719,9 @@ class DBOSConfiguredInstance:
722
719
  """
723
720
  Base class for classes containing DBOS member functions.
724
721
 
725
- When a class contains workflow, transaction, and communicator functions that access
726
- instance state, the DBOS workflow executor needs a name for the instance. This name
727
- is recorded in the database, and used to refer to the proper instance upon recovery.
722
+ When a class contains DBOS functions that access instance state, the DBOS workflow
723
+ executor needs a name for the instance. This name is recorded in the database, and
724
+ used to refer to the proper instance upon recovery.
728
725
 
729
726
  Use `DBOSConfiguredInstance` to specify the instance name and register the instance
730
727
  with the DBOS workflow executor.
@@ -32,7 +32,7 @@ class DBOSErrorCode(Enum):
32
32
  WorkflowFunctionNotFound = 4
33
33
  NonExistentWorkflowError = 5
34
34
  DuplicateWorkflowEventError = 6
35
- CommunicatorMaxRetriesExceeded = 7
35
+ MaxStepRetriesExceeded = 7
36
36
  NotAuthorized = 8
37
37
 
38
38
 
@@ -106,11 +106,11 @@ class DBOSNotAuthorizedError(DBOSException):
106
106
  )
107
107
 
108
108
 
109
- class DBOSCommunicatorMaxRetriesExceededError(DBOSException):
110
- """Exception raised when a communicator function was retried the maximimum number of times without success."""
109
+ class DBOSMaxStepRetriesExceeded(DBOSException):
110
+ """Exception raised when a step was retried the maximimum number of times without success."""
111
111
 
112
112
  def __init__(self) -> None:
113
113
  super().__init__(
114
- "Communicator reached maximum retries.",
115
- dbos_error_code=DBOSErrorCode.CommunicatorMaxRetriesExceeded.value,
114
+ "Step reached maximum retries.",
115
+ dbos_error_code=DBOSErrorCode.MaxStepRetriesExceeded.value,
116
116
  )
@@ -16,7 +16,7 @@ def set_dbos_func_name(f: Any, name: str) -> None:
16
16
  setattr(f, "dbos_function_name", name)
17
17
 
18
18
 
19
- TempWorkflowType = Literal["transaction", "communicator", "send", None]
19
+ TempWorkflowType = Literal["transaction", "step", "send", None]
20
20
 
21
21
 
22
22
  def get_temp_workflow_type(f: Any) -> TempWorkflowType: