dbos 0.24.0a1__py3-none-any.whl → 0.24.0a4__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.

@@ -3,7 +3,7 @@ import time
3
3
  import traceback
4
4
  from typing import TYPE_CHECKING, Optional
5
5
 
6
- from websockets import ConnectionClosed, ConnectionClosedOK
6
+ from websockets import ConnectionClosed, ConnectionClosedOK, InvalidStatus
7
7
  from websockets.sync.client import connect
8
8
  from websockets.sync.connection import Connection
9
9
 
@@ -39,12 +39,12 @@ class ConductorWebsocket(threading.Thread):
39
39
  message = websocket.recv()
40
40
  if not isinstance(message, str):
41
41
  self.dbos.logger.warning(
42
- "Receieved unexpected non-str message"
42
+ "Received unexpected non-str message"
43
43
  )
44
44
  continue
45
45
  base_message = p.BaseMessage.from_json(message)
46
- type = base_message.type
47
- if type == p.MessageType.EXECUTOR_INFO:
46
+ msg_type = base_message.type
47
+ if msg_type == p.MessageType.EXECUTOR_INFO:
48
48
  info_response = p.ExecutorInfoResponse(
49
49
  type=p.MessageType.EXECUTOR_INFO,
50
50
  request_id=base_message.request_id,
@@ -53,7 +53,7 @@ class ConductorWebsocket(threading.Thread):
53
53
  )
54
54
  websocket.send(info_response.to_json())
55
55
  self.dbos.logger.info("Connected to DBOS conductor")
56
- elif type == p.MessageType.RECOVERY:
56
+ elif msg_type == p.MessageType.RECOVERY:
57
57
  recovery_message = p.RecoveryRequest.from_json(message)
58
58
  success = True
59
59
  try:
@@ -71,7 +71,7 @@ class ConductorWebsocket(threading.Thread):
71
71
  success=success,
72
72
  )
73
73
  websocket.send(recovery_response.to_json())
74
- elif type == p.MessageType.CANCEL:
74
+ elif msg_type == p.MessageType.CANCEL:
75
75
  cancel_message = p.CancelRequest.from_json(message)
76
76
  success = True
77
77
  try:
@@ -87,7 +87,7 @@ class ConductorWebsocket(threading.Thread):
87
87
  success=success,
88
88
  )
89
89
  websocket.send(cancel_response.to_json())
90
- elif type == p.MessageType.RESUME:
90
+ elif msg_type == p.MessageType.RESUME:
91
91
  resume_message = p.ResumeRequest.from_json(message)
92
92
  success = True
93
93
  try:
@@ -103,7 +103,7 @@ class ConductorWebsocket(threading.Thread):
103
103
  success=success,
104
104
  )
105
105
  websocket.send(resume_response.to_json())
106
- elif type == p.MessageType.RESTART:
106
+ elif msg_type == p.MessageType.RESTART:
107
107
  restart_message = p.RestartRequest.from_json(message)
108
108
  success = True
109
109
  try:
@@ -119,7 +119,7 @@ class ConductorWebsocket(threading.Thread):
119
119
  success=success,
120
120
  )
121
121
  websocket.send(restart_response.to_json())
122
- elif type == p.MessageType.LIST_WORKFLOWS:
122
+ elif msg_type == p.MessageType.LIST_WORKFLOWS:
123
123
  list_workflows_message = p.ListWorkflowsRequest.from_json(
124
124
  message
125
125
  )
@@ -147,7 +147,7 @@ class ConductorWebsocket(threading.Thread):
147
147
  ],
148
148
  )
149
149
  websocket.send(list_workflows_response.to_json())
150
- elif type == p.MessageType.LIST_QUEUED_WORKFLOWS:
150
+ elif msg_type == p.MessageType.LIST_QUEUED_WORKFLOWS:
151
151
  list_queued_workflows_message = (
152
152
  p.ListQueuedWorkflowsRequest.from_json(message)
153
153
  )
@@ -175,7 +175,7 @@ class ConductorWebsocket(threading.Thread):
175
175
  )
176
176
  )
177
177
  websocket.send(list_queued_workflows_response.to_json())
178
- elif type == p.MessageType.GET_WORKFLOW:
178
+ elif msg_type == p.MessageType.GET_WORKFLOW:
179
179
  get_workflow_message = p.GetWorkflowRequest.from_json(
180
180
  message
181
181
  )
@@ -194,8 +194,26 @@ class ConductorWebsocket(threading.Thread):
194
194
  ),
195
195
  )
196
196
  websocket.send(get_workflow_response.to_json())
197
+ elif msg_type == p.MessageType.EXIST_PENDING_WORKFLOWS:
198
+ exist_pending_workflows_message = (
199
+ p.ExistPendingWorkflowsRequest.from_json(message)
200
+ )
201
+ pending_wfs = self.dbos._sys_db.get_pending_workflows(
202
+ exist_pending_workflows_message.executor_id,
203
+ exist_pending_workflows_message.application_version,
204
+ )
205
+ exist_pending_workflows_response = (
206
+ p.ExistPendingWorkflowsResponse(
207
+ type=p.MessageType.EXIST_PENDING_WORKFLOWS,
208
+ request_id=base_message.request_id,
209
+ exist=len(pending_wfs) > 0,
210
+ )
211
+ )
212
+ websocket.send(exist_pending_workflows_response.to_json())
197
213
  else:
198
- self.dbos.logger.warning(f"Unexpected message type: {type}")
214
+ self.dbos.logger.warning(
215
+ f"Unexpected message type: {msg_type}"
216
+ )
199
217
  except ConnectionClosedOK:
200
218
  self.dbos.logger.info("Conductor connection terminated")
201
219
  break
@@ -205,6 +223,14 @@ class ConductorWebsocket(threading.Thread):
205
223
  )
206
224
  time.sleep(1)
207
225
  continue
226
+ except InvalidStatus as e:
227
+ # This happens when it cannot open a connection to the conductor. E.g., the conductor rejects the request
228
+ json_data = e.response.body.decode("utf-8")
229
+ self.dbos.logger.error(
230
+ f"Failed to connect to conductor. Retrying: {str(e) }. Details: {json_data}"
231
+ )
232
+ time.sleep(1)
233
+ continue
208
234
  except Exception as e:
209
235
  self.dbos.logger.error(
210
236
  f"Unexpected exception in connection to conductor. Reconnecting: {e}"
@@ -15,6 +15,7 @@ class MessageType(str, Enum):
15
15
  RESUME = "resume"
16
16
  RESTART = "restart"
17
17
  GET_WORKFLOW = "get_workflow"
18
+ EXIST_PENDING_WORKFLOWS = "exist_pending_workflows"
18
19
 
19
20
 
20
21
  T = TypeVar("T", bound="BaseMessage")
@@ -195,3 +196,14 @@ class GetWorkflowRequest(BaseMessage):
195
196
  @dataclass
196
197
  class GetWorkflowResponse(BaseMessage):
197
198
  output: Optional[WorkflowsOutput]
199
+
200
+
201
+ @dataclass
202
+ class ExistPendingWorkflowsRequest(BaseMessage):
203
+ executor_id: str
204
+ application_version: str
205
+
206
+
207
+ @dataclass
208
+ class ExistPendingWorkflowsResponse(BaseMessage):
209
+ exist: bool
dbos/_debug.py CHANGED
@@ -1,8 +1,11 @@
1
1
  import re
2
2
  import runpy
3
3
  import sys
4
+ from pathlib import Path
4
5
  from typing import Union
5
6
 
7
+ from fastapi_cli.discover import get_module_data_from_path
8
+
6
9
  from dbos import DBOS
7
10
 
8
11
 
@@ -33,7 +36,10 @@ def debug_workflow(workflow_id: str, entrypoint: Union[str, PythonModule]) -> No
33
36
  def parse_start_command(command: str) -> Union[str, PythonModule]:
34
37
  match = re.match(r"fastapi\s+run\s+(\.?[\w/]+\.py)", command)
35
38
  if match:
36
- return match.group(1)
39
+ # Mirror the logic in fastapi's run command by converting the path argument to a module
40
+ mod_data = get_module_data_from_path(Path(match.group(1)))
41
+ sys.path.insert(0, str(mod_data.extra_sys_path))
42
+ return PythonModule(mod_data.module_import_str)
37
43
  match = re.match(r"python3?\s+(\.?[\w/]+\.py)", command)
38
44
  if match:
39
45
  return match.group(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 0.24.0a1
3
+ Version: 0.24.0a4
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-0.24.0a1.dist-info/METADATA,sha256=UuArfBoytGeWjufDI1gg6odzVSbkLTCGu_ZYtZFe_uM,5555
2
- dbos-0.24.0a1.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- dbos-0.24.0a1.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
- dbos-0.24.0a1.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
1
+ dbos-0.24.0a4.dist-info/METADATA,sha256=WqbCY_vtpMPqlArkZMKDKE3NDx7WhS-NrwTPh6jEj2c,5555
2
+ dbos-0.24.0a4.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ dbos-0.24.0a4.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
+ dbos-0.24.0a4.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
5
5
  dbos/__init__.py,sha256=CxRHBHEthPL4PZoLbZhp3rdm44-KkRTT2-7DkK9d4QQ,724
6
6
  dbos/__main__.py,sha256=P7jAr-7L9XE5mrsQ7i4b-bLr2ap1tCQfhMByLCRWDj0,568
7
7
  dbos/_admin_server.py,sha256=YiVn5lywz2Vg8_juyNHOYl0HVEy48--7b4phwK7r92o,5732
@@ -10,15 +10,15 @@ 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
12
12
  dbos/_cloudutils/databases.py,sha256=_shqaqSvhY4n2ScgQ8IP5PDZvzvcx3YBKV8fj-cxhSY,8543
13
- dbos/_conductor/conductor.py,sha256=uX6DsAw0vpu4Gf5pxZJL7YrMSfJptCvRCnt14AUURFo,11123
14
- dbos/_conductor/protocol.py,sha256=HLHS1bOdFdQhwA05wXDCd3O704ki72ju1UUBXz0UB-0,4841
13
+ dbos/_conductor/conductor.py,sha256=tvB1k8V3ZsI3MBEcG9sIkfbsHHx_Cvh0FZAi9vSPrXU,12698
14
+ dbos/_conductor/protocol.py,sha256=Lo-DjvKevTS2uKyITLjjVp56rBRzaQfKkKpieZz3VAs,5088
15
15
  dbos/_context.py,sha256=Ue5qu3rzLfRmPkz-UUZi9ZS8iXpapRN0NTM4mbA2QmQ,17738
16
16
  dbos/_core.py,sha256=UQb068FT59Op-F5RmtxreSeSQ1_wljOso0dQCUOPrC4,37528
17
17
  dbos/_croniter.py,sha256=XHAyUyibs_59sJQfSNWkP7rqQY6_XrlfuuCxk4jYqek,47559
18
18
  dbos/_db_wizard.py,sha256=6tfJaCRa1NtkUdNW75a2yvi_mEgnPJ9C1HP2zPG1hCU,8067
19
19
  dbos/_dbos.py,sha256=0kX3fgdTqAn-eMKSbh73LFVR08YPMoB030g4dzvc9Yk,41150
20
20
  dbos/_dbos_config.py,sha256=_VETbEsMZ66563A8sX05B_coKz2BrILbIm9H5BmnPmk,9572
21
- dbos/_debug.py,sha256=wcvjM2k4BrK7mlYjImUZXNBUB00fPGjQrNimZXlj76c,1491
21
+ dbos/_debug.py,sha256=mmgvLkqlrljMBBow9wk01PPur9kUf2rI_11dTJXY4gw,1822
22
22
  dbos/_error.py,sha256=xqB7b7g5AF_OwOvqLKLXL1xldn2gAtORix2ZC2B8zK0,5089
23
23
  dbos/_fastapi.py,sha256=ke03vqsSYDnO6XeOtOVFXj0-f-v1MGsOxa9McaROvNc,3616
24
24
  dbos/_flask.py,sha256=DZKUZR5-xOzPI7tYZ53r2PvvHVoAb8SYwLzMVFsVfjI,2608
@@ -65,4 +65,4 @@ dbos/cli/cli.py,sha256=ThomRytw7EP5iOcrjEgwnpaWgXNTLfnFEBBvCGHxtJs,15590
65
65
  dbos/dbos-config.schema.json,sha256=X5TpXNcARGceX0zQs0fVgtZW_Xj9uBbY5afPt9Rz9yk,5741
66
66
  dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
67
67
  version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
68
- dbos-0.24.0a1.dist-info/RECORD,,
68
+ dbos-0.24.0a4.dist-info/RECORD,,