reactor-runtime 2.7.8__tar.gz → 2.7.9__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.
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/PKG-INFO +1 -1
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/pyproject.toml +2 -2
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/model_state.py +30 -3
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtime_api.py +131 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime.egg-info/PKG-INFO +1 -1
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/README.md +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/setup.cfg +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/api/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/config.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/experiment/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/experiment/session.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/defaults.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/driver/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/driver/pipeline_executor.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/driver/step_result.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/connected.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/event.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/messages.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/upload.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/internal/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/internal/input_buffer.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/internal/output_buffer.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/internal/reactor_core.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/decorators.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/handlers.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/reactor_model.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/pipeline/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/pipeline/idle.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/pipeline/input_state.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/pipeline/reactor_pipeline.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/descriptors.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/input.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/output.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/upload.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/base.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/file.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/otlp.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/helpers.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/nvml_sampler.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/plotting/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/plotting/plot_profiling.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/profiler.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/singleton.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/torch_chunk_profiler.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/chunk_encoder.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/chunk_uploader.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/config.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/markers.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/session_recorder.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/sinks.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/track_resolver.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/headless/config.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/headless/headless_runtime.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/headless/input_feeder.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/http/config.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/http/http_runtime.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/http/types.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/schema.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/schema_validator.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/__main__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/commands/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/commands/run.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/commands/schema.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/main.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/utils/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/utils/config.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/utils/runtime.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/audio_track.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/client.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/frame_conversion.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/ice_connection.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/video_track.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/config.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/events.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/client.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/av1.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/base.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/factory.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/h264.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/h265.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/opus.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/vp8.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/decoders/vp9.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/av1.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/base.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/factory.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/h264.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/h265.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/opus.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/vp8.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/encoders/vp9.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/gst.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/gst_helpers.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/probes/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/probes/fps_probe.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/receiver/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/receiver/audio.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/receiver/base.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/receiver/video.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sdp/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sdp/bundle.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sdp/codec.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sdp/extmap.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sdp/ice.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sender/__init__.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sender/audio.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sender/base.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sender/video.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/settings.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/signals.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/ice_uris.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/interface.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/media.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/types.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/utils/launch.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/utils/loader.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/utils/log.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/utils/messages.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/utils/paths.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/utils/ports.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/utils/typing.py +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime.egg-info/SOURCES.txt +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime.egg-info/dependency_links.txt +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime.egg-info/requires.txt +0 -0
- {reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "reactor_runtime"
|
|
7
|
-
version = "2.7.
|
|
7
|
+
version = "2.7.9"
|
|
8
8
|
description = "Reactor runtime with public model API"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Reactor", email = "team@reactor.inc" }
|
|
@@ -87,4 +87,4 @@ gst = [
|
|
|
87
87
|
# Legacy releases used `X.Y.Z-g<short-sha>` (e.g. `1.4.1-g5660eed`); the wheel
|
|
88
88
|
# stripped the `-g<sha>` suffix. fetch-proto.py still understands that shape
|
|
89
89
|
# for back-compat with old pins, but new bumps should track the calendar format.
|
|
90
|
-
version = "1.
|
|
90
|
+
version = "1.20260527.14467"
|
|
@@ -31,6 +31,7 @@ class ModelEvent(Enum):
|
|
|
31
31
|
CLEANUP_COMPLETE = "cleanup_complete"
|
|
32
32
|
EVICTION = "eviction"
|
|
33
33
|
IDLING = "idling"
|
|
34
|
+
SESSION_ACTIVE = "session_active"
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
class ModelStateMachine:
|
|
@@ -72,6 +73,15 @@ class ModelStateMachine:
|
|
|
72
73
|
ModelEvent.IDLING: [
|
|
73
74
|
(ModelState.READY, ModelState.READY),
|
|
74
75
|
],
|
|
76
|
+
# SESSION_ACTIVE is the analog of IDLING during a live session: a
|
|
77
|
+
# periodic liveness ping sent while the runtime is serving a
|
|
78
|
+
# session (WAITING / STREAMING / ORPHANED). All three transitions
|
|
79
|
+
# are self-loops since the event carries no state change.
|
|
80
|
+
ModelEvent.SESSION_ACTIVE: [
|
|
81
|
+
(ModelState.WAITING, ModelState.WAITING),
|
|
82
|
+
(ModelState.STREAMING, ModelState.STREAMING),
|
|
83
|
+
(ModelState.ORPHANED, ModelState.ORPHANED),
|
|
84
|
+
],
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
def __init__(self, initial_state: ModelState = ModelState.CREATED):
|
|
@@ -98,7 +108,10 @@ class ModelStateMachine:
|
|
|
98
108
|
|
|
99
109
|
if to_state is None:
|
|
100
110
|
log_fn = logger.warning
|
|
101
|
-
|
|
111
|
+
# IDLING and SESSION_ACTIVE are high-frequency liveness pings;
|
|
112
|
+
# legitimate races with state transitions can produce rejected
|
|
113
|
+
# events that don't deserve a warning.
|
|
114
|
+
if event in (ModelEvent.IDLING, ModelEvent.SESSION_ACTIVE):
|
|
102
115
|
log_fn = logger.debug
|
|
103
116
|
log_fn(
|
|
104
117
|
"Illegal state transition",
|
|
@@ -108,7 +121,7 @@ class ModelStateMachine:
|
|
|
108
121
|
return False
|
|
109
122
|
|
|
110
123
|
log_fn = logger.info
|
|
111
|
-
if event
|
|
124
|
+
if event in (ModelEvent.IDLING, ModelEvent.SESSION_ACTIVE):
|
|
112
125
|
log_fn = logger.debug
|
|
113
126
|
|
|
114
127
|
log_fn(
|
|
@@ -145,7 +158,18 @@ class ModelStateMachine:
|
|
|
145
158
|
handler(**kwargs)
|
|
146
159
|
|
|
147
160
|
def _call_enter_handler(self, state: ModelState, previous_state: ModelState):
|
|
148
|
-
"""Call the appropriate on_enter_<state> method.
|
|
161
|
+
"""Call the appropriate on_enter_<state> method.
|
|
162
|
+
|
|
163
|
+
Self-loop transitions (``state == previous_state``) skip the
|
|
164
|
+
``on_enter_*`` hook — those hooks are designed to run on actual
|
|
165
|
+
state changes, not on every heartbeat. This matters for
|
|
166
|
+
liveness-ping events like ``IDLING`` and ``SESSION_ACTIVE`` whose
|
|
167
|
+
from/to states are identical: re-running ``on_enter_WAITING`` /
|
|
168
|
+
``on_enter_ORPHANED`` on every tick would, e.g., cancel and
|
|
169
|
+
restart the orphan timeout, preventing it from ever firing.
|
|
170
|
+
"""
|
|
171
|
+
if state == previous_state:
|
|
172
|
+
return
|
|
149
173
|
handler_name = f"on_enter_{state.value}"
|
|
150
174
|
handler = getattr(self, handler_name, None)
|
|
151
175
|
if handler:
|
|
@@ -191,6 +215,9 @@ class ModelStateMachine:
|
|
|
191
215
|
def on_before_idling(self, **kwargs):
|
|
192
216
|
pass
|
|
193
217
|
|
|
218
|
+
def on_before_session_active(self, **kwargs):
|
|
219
|
+
pass
|
|
220
|
+
|
|
194
221
|
# on_enter_<state> methods
|
|
195
222
|
def on_enter_CREATED(self, previous_state: ModelState):
|
|
196
223
|
pass
|
|
@@ -100,6 +100,13 @@ def _iter_strings(value: Any) -> Iterator[str]:
|
|
|
100
100
|
_IDLING_INTERVAL_ENV_VAR = "IDLING_INTERVAL_SECONDS"
|
|
101
101
|
_DEFAULT_IDLING_INTERVAL = 30.0
|
|
102
102
|
|
|
103
|
+
# Periodic SESSION_ACTIVE liveness ping. Sent while the runtime is serving
|
|
104
|
+
# a session (WAITING / STREAMING / ORPHANED). Default cadence matches the
|
|
105
|
+
# Supervisor's reaper tick (10s); the Supervisor declares a session lost
|
|
106
|
+
# after 3 missed intervals.
|
|
107
|
+
_SESSION_ACTIVE_INTERVAL_ENV_VAR = "SESSION_ACTIVE_INTERVAL_SECONDS"
|
|
108
|
+
_DEFAULT_SESSION_ACTIVE_INTERVAL = 10.0
|
|
109
|
+
|
|
103
110
|
_PING_TIMEOUT_ENV_VAR = "WEBRTC_CLIENT_PING_TIMEOUT_SECONDS"
|
|
104
111
|
_DEFAULT_PING_TIMEOUT = 20.0
|
|
105
112
|
|
|
@@ -130,6 +137,12 @@ class RuntimeConfig:
|
|
|
130
137
|
# Priority: ENV > CLI > default. Set to None to use default.
|
|
131
138
|
idling_interval: Optional[float] = None
|
|
132
139
|
|
|
140
|
+
# Session-active heartbeat interval in seconds. Emitted while the
|
|
141
|
+
# runtime is serving a session (WAITING / STREAMING / ORPHANED) so
|
|
142
|
+
# the Supervisor can detect abruptly terminated sessions.
|
|
143
|
+
# Priority: ENV > CLI > default. Set to None to use default.
|
|
144
|
+
session_active_interval: Optional[float] = None
|
|
145
|
+
|
|
133
146
|
# WebRTC client-ping watchdog timeout (seconds). Priority: ENV > CLI > default.
|
|
134
147
|
# Resolved to a concrete float in __post_init__; non-positive disables the watchdog.
|
|
135
148
|
ping_timeout: Optional[float] = None
|
|
@@ -162,6 +175,26 @@ class RuntimeConfig:
|
|
|
162
175
|
if self.idling_interval is None:
|
|
163
176
|
self.idling_interval = _DEFAULT_IDLING_INTERVAL
|
|
164
177
|
|
|
178
|
+
# Resolve session_active_interval: ENV > CLI > default, same shape
|
|
179
|
+
# as idling_interval above.
|
|
180
|
+
sa_env_val = os.getenv(_SESSION_ACTIVE_INTERVAL_ENV_VAR)
|
|
181
|
+
if sa_env_val:
|
|
182
|
+
try:
|
|
183
|
+
self.session_active_interval = float(sa_env_val)
|
|
184
|
+
except ValueError:
|
|
185
|
+
logger.warning(
|
|
186
|
+
"Invalid session-active interval env value, falling back to default",
|
|
187
|
+
env_var=_SESSION_ACTIVE_INTERVAL_ENV_VAR,
|
|
188
|
+
value=sa_env_val,
|
|
189
|
+
)
|
|
190
|
+
if (
|
|
191
|
+
self.session_active_interval is not None
|
|
192
|
+
and self.session_active_interval <= 0
|
|
193
|
+
):
|
|
194
|
+
self.session_active_interval = None
|
|
195
|
+
if self.session_active_interval is None:
|
|
196
|
+
self.session_active_interval = _DEFAULT_SESSION_ACTIVE_INTERVAL
|
|
197
|
+
|
|
165
198
|
# Resolve ping_timeout: ENV > CLI > default (reject non-finite floats)
|
|
166
199
|
resolved_ping: Optional[float] = None
|
|
167
200
|
ping_env = os.getenv(_PING_TIMEOUT_ENV_VAR)
|
|
@@ -239,6 +272,17 @@ class RuntimeConfig:
|
|
|
239
272
|
help=f"Idling event interval ({_IDLING_INTERVAL_ENV_VAR} env overrides). "
|
|
240
273
|
f"Default: {_DEFAULT_IDLING_INTERVAL}s",
|
|
241
274
|
)
|
|
275
|
+
parser.add_argument(
|
|
276
|
+
"--session-active-interval",
|
|
277
|
+
type=float,
|
|
278
|
+
default=None,
|
|
279
|
+
dest="session_active_interval",
|
|
280
|
+
help=(
|
|
281
|
+
"SESSION_ACTIVE liveness event interval, emitted while a "
|
|
282
|
+
f"session is active ({_SESSION_ACTIVE_INTERVAL_ENV_VAR} env "
|
|
283
|
+
f"overrides). Default: {_DEFAULT_SESSION_ACTIVE_INTERVAL}s"
|
|
284
|
+
),
|
|
285
|
+
)
|
|
242
286
|
parser.add_argument(
|
|
243
287
|
"--profiling-dir",
|
|
244
288
|
type=str,
|
|
@@ -291,6 +335,11 @@ class Runtime(ModelStateMachine, ABC):
|
|
|
291
335
|
# Idling task - sends periodic IDLING events when in READY state
|
|
292
336
|
self._idling_task: Optional[asyncio.Task] = None
|
|
293
337
|
|
|
338
|
+
# Session-active task - sends periodic SESSION_ACTIVE events while
|
|
339
|
+
# the runtime is serving a session (WAITING / STREAMING / ORPHANED).
|
|
340
|
+
# Lifecycle is gated by on_enter_* state hooks.
|
|
341
|
+
self._session_active_task: Optional[asyncio.Task] = None
|
|
342
|
+
|
|
294
343
|
# Trickle-ICE buffer
|
|
295
344
|
# Browsers start emitting ICE candidates as soon as
|
|
296
345
|
# ``setLocalDescription`` runs — typically *before* the SDP
|
|
@@ -478,6 +527,9 @@ class Runtime(ModelStateMachine, ABC):
|
|
|
478
527
|
:meth:`add_ice_candidate`.
|
|
479
528
|
"""
|
|
480
529
|
self._cancel_orphan_timeout()
|
|
530
|
+
# Idempotent: a session arriving here from WAITING will already
|
|
531
|
+
# have armed the loop; re-arming on ORPHANED -> STREAMING is a no-op.
|
|
532
|
+
self._start_session_active_loop()
|
|
481
533
|
|
|
482
534
|
# Replay buffered trickle ICE candidates onto the freshly
|
|
483
535
|
# installed transport. Scheduled via create_task because
|
|
@@ -498,15 +550,24 @@ class Runtime(ModelStateMachine, ABC):
|
|
|
498
550
|
"""
|
|
499
551
|
self._clear_pending_ice_candidates()
|
|
500
552
|
self._start_orphan_timeout()
|
|
553
|
+
# Keep emitting SESSION_ACTIVE while orphaned: the runtime is still
|
|
554
|
+
# "owning" the session, just temporarily without a client.
|
|
555
|
+
self._start_session_active_loop()
|
|
501
556
|
|
|
502
557
|
def on_enter_WAITING(self, previous_state: ModelState) -> None:
|
|
503
558
|
"""Handler called when the session enters the WAITING state.
|
|
504
559
|
Starts the orphan timeout.
|
|
505
560
|
"""
|
|
506
561
|
self._start_orphan_timeout()
|
|
562
|
+
# Arm SESSION_ACTIVE pings as soon as the runtime accepts a session,
|
|
563
|
+
# before the client has even connected.
|
|
564
|
+
self._start_session_active_loop()
|
|
507
565
|
|
|
508
566
|
def on_enter_TERMINATED(self, previous_state: ModelState) -> None:
|
|
509
567
|
"""TERMINATED means the runtime should exit."""
|
|
568
|
+
# Cancel the session-active loop synchronously via task.cancel();
|
|
569
|
+
# the awaited stop happens in _shutdown_cleanup.
|
|
570
|
+
self._cancel_session_active_task()
|
|
510
571
|
self._shutdown_event.set()
|
|
511
572
|
|
|
512
573
|
def on_enter_READY(self, previous_state: ModelState) -> None:
|
|
@@ -517,6 +578,8 @@ class Runtime(ModelStateMachine, ABC):
|
|
|
517
578
|
shutdown event if SIGTERM was received earlier.
|
|
518
579
|
"""
|
|
519
580
|
self._clear_pending_ice_candidates()
|
|
581
|
+
# Back to READY: session is fully unwound, stop the per-session loop.
|
|
582
|
+
self._cancel_session_active_task()
|
|
520
583
|
if self._shutdown_pending:
|
|
521
584
|
self._shutdown_event.set()
|
|
522
585
|
|
|
@@ -530,6 +593,9 @@ class Runtime(ModelStateMachine, ABC):
|
|
|
530
593
|
"""
|
|
531
594
|
self._cancel_orphan_timeout()
|
|
532
595
|
self._clear_pending_ice_candidates()
|
|
596
|
+
# Session is wrapping up; stop emitting SESSION_ACTIVE so we don't
|
|
597
|
+
# race the CLEANUP_COMPLETE / STOP_SESSION events.
|
|
598
|
+
self._cancel_session_active_task()
|
|
533
599
|
|
|
534
600
|
if self.model is not None:
|
|
535
601
|
self.model._push_event(Disconnected())
|
|
@@ -1212,6 +1278,7 @@ class Runtime(ModelStateMachine, ABC):
|
|
|
1212
1278
|
async def _shutdown_cleanup(self) -> None:
|
|
1213
1279
|
"""Internal shutdown cleanup implementation."""
|
|
1214
1280
|
await self._stop_idling_loop()
|
|
1281
|
+
await self._stop_session_active_loop()
|
|
1215
1282
|
|
|
1216
1283
|
try:
|
|
1217
1284
|
if self.session_running or self.current_state == ModelState.WAITING:
|
|
@@ -1325,3 +1392,67 @@ class Runtime(ModelStateMachine, ABC):
|
|
|
1325
1392
|
break
|
|
1326
1393
|
except Exception:
|
|
1327
1394
|
pass
|
|
1395
|
+
|
|
1396
|
+
# -----------------------------------------------------------------
|
|
1397
|
+
# Session-active heartbeat
|
|
1398
|
+
# -----------------------------------------------------------------
|
|
1399
|
+
|
|
1400
|
+
def _start_session_active_loop(self) -> None:
|
|
1401
|
+
"""Start the session-active heartbeat loop.
|
|
1402
|
+
|
|
1403
|
+
Emits ``SESSION_ACTIVE`` events while the runtime is serving a
|
|
1404
|
+
session, giving the Supervisor a liveness signal during the
|
|
1405
|
+
WAITING / STREAMING / ORPHANED states. Idempotent: a second call
|
|
1406
|
+
while the loop is already running is a no-op, so it's safe to
|
|
1407
|
+
invoke from every relevant on_enter_* hook.
|
|
1408
|
+
"""
|
|
1409
|
+
if self._session_active_task is not None:
|
|
1410
|
+
return
|
|
1411
|
+
self._session_active_task = asyncio.create_task(self._session_active_loop())
|
|
1412
|
+
|
|
1413
|
+
def _cancel_session_active_task(self) -> None:
|
|
1414
|
+
"""Cancel the session-active loop synchronously.
|
|
1415
|
+
|
|
1416
|
+
Safe to call from on_enter_* hooks (which run synchronously from
|
|
1417
|
+
``send()``). The task reference is preserved so that
|
|
1418
|
+
``_stop_session_active_loop`` (called from ``_shutdown_cleanup``)
|
|
1419
|
+
can still ``await`` the cancelled task during shutdown; the
|
|
1420
|
+
synchronous ``.cancel()`` call is enough for the on_enter_* hooks.
|
|
1421
|
+
"""
|
|
1422
|
+
if self._session_active_task is not None:
|
|
1423
|
+
self._session_active_task.cancel()
|
|
1424
|
+
|
|
1425
|
+
async def _stop_session_active_loop(self) -> None:
|
|
1426
|
+
"""Cancel the session-active loop and await its exit.
|
|
1427
|
+
|
|
1428
|
+
Called from ``_shutdown_cleanup`` to make sure the loop is fully
|
|
1429
|
+
unwound before the runtime exits.
|
|
1430
|
+
"""
|
|
1431
|
+
task = self._session_active_task
|
|
1432
|
+
if task is None:
|
|
1433
|
+
return
|
|
1434
|
+
task.cancel()
|
|
1435
|
+
self._session_active_task = None
|
|
1436
|
+
try:
|
|
1437
|
+
await task
|
|
1438
|
+
except asyncio.CancelledError:
|
|
1439
|
+
pass
|
|
1440
|
+
|
|
1441
|
+
async def _session_active_loop(self) -> None:
|
|
1442
|
+
"""Background task that periodically triggers SESSION_ACTIVE events.
|
|
1443
|
+
|
|
1444
|
+
Like ``_idling_loop``, the event is rejected by the state machine
|
|
1445
|
+
unless the runtime is in a busy session state (WAITING / STREAMING
|
|
1446
|
+
/ ORPHANED). Rejected events log at debug level, so a late tick
|
|
1447
|
+
racing with a state transition doesn't spam warnings.
|
|
1448
|
+
"""
|
|
1449
|
+
assert self.config.session_active_interval is not None
|
|
1450
|
+
interval = self.config.session_active_interval
|
|
1451
|
+
while True:
|
|
1452
|
+
try:
|
|
1453
|
+
await asyncio.sleep(interval)
|
|
1454
|
+
self.send(ModelEvent.SESSION_ACTIVE)
|
|
1455
|
+
except asyncio.CancelledError:
|
|
1456
|
+
break
|
|
1457
|
+
except Exception:
|
|
1458
|
+
pass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/driver/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/driver/step_result.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/connected.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/event.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/messages.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/events/upload.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/internal/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/decorators.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/handlers.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/model/reactor_model.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/pipeline/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/pipeline/idle.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/descriptors.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/input.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/interface/tracks/output.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/base.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/file.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/backends/otlp.py
RENAMED
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/nvml_sampler.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/profiling/plotting/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/chunk_encoder.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/chunk_uploader.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/session_recorder.py
RENAMED
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/recording/track_resolver.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/headless/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/runtimes/http/http_runtime.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/commands/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/serve/commands/schema.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/audio_track.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/aiortc/video_track.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/__init__.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/gst.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/sdp/ice.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/settings.py
RENAMED
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime/transports/gstreamer/signals.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{reactor_runtime-2.7.8 → reactor_runtime-2.7.9}/src/reactor_runtime.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|