fix(runway): warn and surface session status when avatar leaves before max_duration - #6901
Conversation
aed15bc to
7050285
Compare
|
Thanks for the review, Devin — that's a legitimate catch. Fixed in the force-push to the branch (7050285):
uff check + |
…ration (livekit#6703) Runway silently terminates realtime sessions at ~300 s even when the plugin sends maxDuration=1800 at session-create time. The creation response contains only an id (no echoed duration) so the applied server-side cap is invisible client-side. The avatar participant then disappears mid-session with no warning, leaving the AgentSession running without video. Changes ------- * Track session wall-clock start time ( ime.monotonic()) after _create_session returns so elapsed time can be computed later. * Introduce _session_ending: bool flag; set it eagerly in both _on_agent_session_close and _ensure_end_session_task() so that agent-initiated teardowns are clearly distinguishable from unexpected server-side disconnects. * Register a participant_disconnected listener on the room. When the avatar participant leaves while _session_ending is False: - Log a WARNING with elapsed and (if set) requested max_duration. - When max_duration was requested and the disconnect happens >60 s early, a dedicated message calls out the likely server-side cap. - In both cases, fire an async task to GET /v1/realtime_sessions/{id} and log the Runway-reported status, duration, and ailureCode (new _log_session_status helper), matching the second half of the proposed solution in the issue. * No new public API surface; no new runtime dependencies ( ime is stdlib). Fixes livekit#6703
7050285 to
e804311
Compare
|
Addressed in e804311 (force-pushed). Three issues fixed in one pass: 1. Handler lifetime (this finding):
2. Late task creation during shutdown window:
3. �syncio.ensure_future -> �syncio.create_task (anticipated finding):
Ordering in �close():
oom.off(...) — handler deregistered, no new invocations possible uff check + |
What this fixes
Closes #6703
When using
runway.AvatarSessionwithmax_duration=1800, the Runway server silently terminates sessions at ~300 s. The plugin correctly forwardsmaxDurationin the creation request but the response contains only an{"id": ...}— no echoed duration — so the applied server-side cap is invisible client-side. The avatar participant then leaves the room mid-session with no warning, and the AgentSession continues without video.Changes
livekit-plugins/livekit-plugins-runway/livekit/plugins/runway/avatar.pyTracking + flag (minimal state, no API surface change):
_session_started_at: float | None—time.monotonic()snapshot captured right after_create_sessionreturns._session_ending: bool— set toTruein both_on_agent_session_closeand_ensure_end_session_task()so agent-initiated teardowns are distinguishable from unexpected server-side disconnects.participant_disconnectedlistener registered on the room instart():_session_endingisTrue(normal teardown path).WARNINGwithelapsed_seconds,session_id, and (whenmax_durationwas set and the gap is >60 s) a human-readable note that the server may have applied a lower cap._log_session_status()as a fire-and-forget task._log_session_status(session_id)(new async helper):GET /v1/realtime_sessions/{id}using the already-initialised HTTP session.status,duration, andfailureCodefields atWARNINGso operators can see what Runway recorded without reading the issue tracker.DEBUG— never raises, never blocks the session.Why this approach
The issue's proposed solution asks for two things:
participant_disconnectedhandler.status,duration,failureCode) from the GET endpoint → covered by_log_session_status.Both are best-effort: they surface information for operators without changing any error paths or adding retry logic, keeping the change minimal and safe.
No-API-change guarantee
timeis stdlib)._ensure_end_session_task,_end_runway_realtime_session,_cancel_runway_realtime_session) are unchanged in their async logic; only_session_ending = Trueis added before the task is created.How it was tested
ruff check --fix→All checks passed!ruff format→1 file reformatted(onlyasyncio.ensure_future(...)call condensed to one line by the formatter), then re-checked →All checks passed!_cancel_runway_realtime_session. I have flagged that dedicated unit tests could mock theparticipant_disconnectedevent and theaiohttpGET call — happy to add them if the maintainers want to introduce a test harness for this plugin.