dbos 1.3.0a8__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dbos/_dbos.py +8 -1
- dbos/_event_loop.py +18 -0
- dbos/_fastapi.py +4 -5
- dbos/_logger.py +17 -11
- {dbos-1.3.0a8.dist-info → dbos-1.4.0.dist-info}/METADATA +1 -1
- {dbos-1.3.0a8.dist-info → dbos-1.4.0.dist-info}/RECORD +9 -9
- {dbos-1.3.0a8.dist-info → dbos-1.4.0.dist-info}/WHEEL +0 -0
- {dbos-1.3.0a8.dist-info → dbos-1.4.0.dist-info}/entry_points.txt +0 -0
- {dbos-1.3.0a8.dist-info → dbos-1.4.0.dist-info}/licenses/LICENSE +0 -0
dbos/_dbos.py
CHANGED
@@ -100,7 +100,13 @@ from ._error import (
|
|
100
100
|
DBOSNonExistentWorkflowError,
|
101
101
|
)
|
102
102
|
from ._event_loop import BackgroundEventLoop
|
103
|
-
from ._logger import
|
103
|
+
from ._logger import (
|
104
|
+
add_otlp_to_all_loggers,
|
105
|
+
add_transformer_to_all_loggers,
|
106
|
+
config_logger,
|
107
|
+
dbos_logger,
|
108
|
+
init_logger,
|
109
|
+
)
|
104
110
|
from ._workflow_commands import get_workflow, list_workflow_steps
|
105
111
|
|
106
112
|
# Most DBOS functions are just any callable F, so decorators / wrappers work on F
|
@@ -514,6 +520,7 @@ class DBOS:
|
|
514
520
|
for handler in dbos_logger.handlers:
|
515
521
|
handler.flush()
|
516
522
|
add_otlp_to_all_loggers()
|
523
|
+
add_transformer_to_all_loggers()
|
517
524
|
except Exception:
|
518
525
|
dbos_logger.error(f"DBOS failed to launch: {traceback.format_exc()}")
|
519
526
|
raise
|
dbos/_event_loop.py
CHANGED
@@ -7,9 +7,13 @@ class BackgroundEventLoop:
|
|
7
7
|
"""
|
8
8
|
This is the event loop to which DBOS submits any coroutines that are not started from within an event loop.
|
9
9
|
In particular, coroutines submitted to queues (such as from scheduled workflows) run on this event loop.
|
10
|
+
|
11
|
+
If a main event loop is known (whether because an event loop existed in the thread that called DBOS.launch
|
12
|
+
or because a FastAPI event loop was detected) then coroutines are submitted there instead.
|
10
13
|
"""
|
11
14
|
|
12
15
|
def __init__(self) -> None:
|
16
|
+
self._main_loop: Optional[asyncio.AbstractEventLoop] = None
|
13
17
|
self._loop: Optional[asyncio.AbstractEventLoop] = None
|
14
18
|
self._thread: Optional[threading.Thread] = None
|
15
19
|
self._running = False
|
@@ -19,6 +23,7 @@ class BackgroundEventLoop:
|
|
19
23
|
if self._running:
|
20
24
|
return
|
21
25
|
|
26
|
+
self.set_main_loop()
|
22
27
|
self._thread = threading.Thread(target=self._run_event_loop, daemon=True)
|
23
28
|
self._thread.start()
|
24
29
|
self._ready.wait() # Wait until the loop is running
|
@@ -58,10 +63,23 @@ class BackgroundEventLoop:
|
|
58
63
|
await asyncio.gather(*tasks, return_exceptions=True)
|
59
64
|
self._loop.stop()
|
60
65
|
|
66
|
+
def set_main_loop(self) -> None:
|
67
|
+
"""
|
68
|
+
Set the main loop to the currently running event loop.
|
69
|
+
Should be called from the main thread.
|
70
|
+
"""
|
71
|
+
try:
|
72
|
+
self._main_loop = asyncio.get_running_loop()
|
73
|
+
except:
|
74
|
+
# There's no running event loop to set
|
75
|
+
pass
|
76
|
+
|
61
77
|
T = TypeVar("T")
|
62
78
|
|
63
79
|
def submit_coroutine(self, coro: Coroutine[Any, Any, T]) -> T:
|
64
80
|
"""Submit a coroutine to the background event loop"""
|
81
|
+
if self._main_loop is not None and self._main_loop.is_running():
|
82
|
+
return asyncio.run_coroutine_threadsafe(coro, self._main_loop).result()
|
65
83
|
if self._loop is None:
|
66
84
|
raise RuntimeError("Event loop not started")
|
67
85
|
return asyncio.run_coroutine_threadsafe(coro, self._loop).result()
|
dbos/_fastapi.py
CHANGED
@@ -44,11 +44,10 @@ class LifespanMiddleware:
|
|
44
44
|
if scope["type"] == "lifespan":
|
45
45
|
|
46
46
|
async def wrapped_send(message: MutableMapping[str, Any]) -> None:
|
47
|
-
if
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
self.dbos._launch()
|
47
|
+
if message["type"] == "lifespan.startup.complete":
|
48
|
+
self.dbos._background_event_loop.set_main_loop()
|
49
|
+
if not self.dbos._launched:
|
50
|
+
self.dbos._launch()
|
52
51
|
elif message["type"] == "lifespan.shutdown.complete":
|
53
52
|
self.dbos._destroy()
|
54
53
|
await send(message)
|
dbos/_logger.py
CHANGED
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
|
16
16
|
from ._dbos_config import ConfigFile
|
17
17
|
|
18
18
|
dbos_logger = logging.getLogger("dbos")
|
19
|
-
_otlp_handler,
|
19
|
+
_otlp_handler, _dbos_log_transformer = None, None
|
20
20
|
|
21
21
|
|
22
22
|
class DBOSLogTransformer(logging.Filter):
|
@@ -93,25 +93,31 @@ def config_logger(config: "ConfigFile") -> None:
|
|
93
93
|
global _otlp_handler
|
94
94
|
_otlp_handler = LoggingHandler(logger_provider=log_provider)
|
95
95
|
|
96
|
-
# Attach DBOS-specific attributes to all log entries.
|
97
|
-
global _otlp_transformer
|
98
|
-
_otlp_transformer = DBOSLogTransformer()
|
99
|
-
|
100
96
|
# Direct DBOS logs to OTLP
|
101
97
|
dbos_logger.addHandler(_otlp_handler)
|
102
|
-
|
98
|
+
|
99
|
+
# Attach DBOS-specific attributes to all log entries.
|
100
|
+
global _dbos_log_transformer
|
101
|
+
_dbos_log_transformer = DBOSLogTransformer()
|
102
|
+
dbos_logger.addFilter(_dbos_log_transformer)
|
103
103
|
|
104
104
|
|
105
105
|
def add_otlp_to_all_loggers() -> None:
|
106
|
-
if _otlp_handler is not None
|
106
|
+
if _otlp_handler is not None:
|
107
107
|
root = logging.root
|
108
|
-
|
109
108
|
root.addHandler(_otlp_handler)
|
110
|
-
root.addFilter(_otlp_transformer)
|
111
|
-
|
112
109
|
for logger_name in root.manager.loggerDict:
|
113
110
|
if logger_name != dbos_logger.name:
|
114
111
|
logger = logging.getLogger(logger_name)
|
115
112
|
if not logger.propagate:
|
116
113
|
logger.addHandler(_otlp_handler)
|
117
|
-
|
114
|
+
|
115
|
+
|
116
|
+
def add_transformer_to_all_loggers() -> None:
|
117
|
+
if _dbos_log_transformer is not None:
|
118
|
+
root = logging.root
|
119
|
+
root.addFilter(_dbos_log_transformer)
|
120
|
+
for logger_name in root.manager.loggerDict:
|
121
|
+
if logger_name != dbos_logger.name:
|
122
|
+
logger = logging.getLogger(logger_name)
|
123
|
+
logger.addFilter(_dbos_log_transformer)
|
@@ -1,7 +1,7 @@
|
|
1
|
-
dbos-1.
|
2
|
-
dbos-1.
|
3
|
-
dbos-1.
|
4
|
-
dbos-1.
|
1
|
+
dbos-1.4.0.dist-info/METADATA,sha256=t968t9UonOSWFDSSmhCujgbvRr_dn1yyVXoJPI31d6U,13265
|
2
|
+
dbos-1.4.0.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
|
3
|
+
dbos-1.4.0.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
|
4
|
+
dbos-1.4.0.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=TWXi4drrzKFpKkUmEJpJkQBZxAtOalnhtYicEn2nDK0,10618
|
@@ -13,17 +13,17 @@ dbos/_conductor/protocol.py,sha256=wgOFZxmS81bv0WCB9dAyg0s6QzldpzVKQDoSPeaX0Ws,6
|
|
13
13
|
dbos/_context.py,sha256=5ajoWAmToAfzzmMLylnJZoL4Ny9rBwZWuG05sXadMIA,24798
|
14
14
|
dbos/_core.py,sha256=hvHKi31-3LG5yfWa-KhsnoFrXsV_eT-GeKIZFT4chx8,48533
|
15
15
|
dbos/_croniter.py,sha256=XHAyUyibs_59sJQfSNWkP7rqQY6_XrlfuuCxk4jYqek,47559
|
16
|
-
dbos/_dbos.py,sha256=
|
16
|
+
dbos/_dbos.py,sha256=GVx3NY59tKWW6nlAtH2PvX4Ne_eOHvY012MtXVK_FQA,47265
|
17
17
|
dbos/_dbos_config.py,sha256=2CC1YR8lP9W-_NsMUMnTnW-v-70KN4XkbJEeNJ78RlQ,20373
|
18
18
|
dbos/_debug.py,sha256=MNlQVZ6TscGCRQeEEL0VE8Uignvr6dPeDDDefS3xgIE,1823
|
19
19
|
dbos/_docker_pg_helper.py,sha256=tLJXWqZ4S-ExcaPnxg_i6cVxL6ZxrYlZjaGsklY-s2I,6115
|
20
20
|
dbos/_error.py,sha256=q0OQJZTbR8FFHV9hEpAGpz9oWBT5L509zUhmyff7FJw,8500
|
21
|
-
dbos/_event_loop.py,sha256=
|
22
|
-
dbos/_fastapi.py,sha256=
|
21
|
+
dbos/_event_loop.py,sha256=cvaFN9-II3MsHEOq8QoICc_8qSKrjikMlLfuhC3Y8Dk,2923
|
22
|
+
dbos/_fastapi.py,sha256=T7YlVY77ASqyTqq0aAPclZ9YzlXdGTT0lEYSwSgt1EE,3151
|
23
23
|
dbos/_flask.py,sha256=Npnakt-a3W5OykONFRkDRnumaDhTQmA0NPdUCGRYKXE,1652
|
24
24
|
dbos/_kafka.py,sha256=pz0xZ9F3X9Ky1k-VSbeF3tfPhP3UPr3lUUhUfE41__U,4198
|
25
25
|
dbos/_kafka_message.py,sha256=NYvOXNG3Qn7bghn1pv3fg4Pbs86ILZGcK4IB-MLUNu0,409
|
26
|
-
dbos/_logger.py,sha256=
|
26
|
+
dbos/_logger.py,sha256=Yde-w0MZt9xT2NBmzcKY9G3mn6OJ5aVJuC5Elm3p4p4,4390
|
27
27
|
dbos/_migrations/env.py,sha256=38SIGVbmn_VV2x2u1aHLcPOoWgZ84eCymf3g_NljmbU,1626
|
28
28
|
dbos/_migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
|
29
29
|
dbos/_migrations/versions/04ca4f231047_workflow_queues_executor_id.py,sha256=ICLPl8CN9tQXMsLDsAj8z1TsL831-Z3F8jSBvrR-wyw,736
|
@@ -69,4 +69,4 @@ dbos/cli/cli.py,sha256=EemOMqNpzSU2BQhAxV_e59pBRITDLwt49HF6W3uWBZg,20775
|
|
69
69
|
dbos/dbos-config.schema.json,sha256=CjaspeYmOkx6Ip_pcxtmfXJTn_YGdSx_0pcPBF7KZmo,6060
|
70
70
|
dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
|
71
71
|
version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
|
72
|
-
dbos-1.
|
72
|
+
dbos-1.4.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|