A socket subscribed to Sessions is not woken between a client's reports #202
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
/Sessionsover the socket is fixed only for whoever asks again. A subscriber is woken by a real report and by nothing else, so a dashboard watching a playing session sees the position it was pushed and then nothing for ten seconds — the symptom #201 described, on the path #201 did not reach.Both sides
Ours:
crates/ephyra-http/src/routes/session/socket.rs:285-291— theSessionsfeed is woken only bycontext.sessions.changes(), whichSessions::playingbumps (crates/ephyra-app/src/session/sessions.rs:431,changed(true)). Nothing bumps it between reports.Upstream is not on a timer either, but the effect is one:
upstream/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs:119—OnSessionManagerPlaybackProgress(…) => SendData(!e.IsAutomated)upstream/Emby.Server.Implementations/Session/SessionManager.cs:953—PlaybackProgress?.Invoke(this, eventArgs)fires on the automated path too, withIsAutomated = trueupstream/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs:169— a non-forcedSendDatastill sends to every connection where(now - state.DateLastSendUtc) >= state.IntervalMsSo upstream's per-session 1s timer (
SessionInfo.cs,Timer(…, 1000, 1000)) reaches the socket as a once-a-second nudge, throttled by each subscription's own interval.What a client sees
A dashboard subscribes
SessionsStartwith"0,1500". The client reports at t=0 and again at t=10.100000000 … 1900000001fe062f5fixed the REST read and SyncPlay's adoption, so anything that asks again gets the advanced value. A socket subscriber never asks again.The open question
Whether the wake is a real cadence (something per playing session, which
crates/ephyra-app/src/session/topics.rs— "Nothing is sent on a timer" — currently forbids, and whichARCHITECTURE.mdforbids foradmin::tasks) or whether theSessionsfeed's existing periodic interval can carry it:BasePeriodicWebSocketListeneris not a wall clock, but it does re-send on the subscription's interval once something marks the feed dirty. The cheap shape to try first is a nudge that costs nothing when no session is playing — if nothing is playing, upstream's timer is not running either.Note that "nothing is sent on a timer" is a true statement about upstream's mechanism and a false one about its effect. Whatever is decided, it needs writing down:
DECISIONS.md:1150-1155is explicit that an undocumented divergence is worse than either answer.Verifying
Two clients against a live pair, one reporting every 10s, a socket subscribed to
SessionsStarton both, and a count of payloads and theirPositionTicksbetween two reports.crates/ephyra-http/tests/sessions.rshas theMovedclock the REST tests use.Found reviewing #201 (
1fe062f5).Measured live against
1fe062f5, so this is not only a reading of the code.A server on :8116 over a copy of
snapshots/enriched; one client (Client="player") posting/Sessions/Playing/Progressevery 10s; one subscriber (Client="Jellyfin Web") on/socketsending{"MessageType":"SessionsStart","Data":"0,1500"}— the interval jellyfin-web's dashboard uses.Two payloads, arriving exactly on the two reports in that window.
0,1500asks for 1.5s; upstream's automated tick would have satisfied it about fourteen times.The REST read is right the whole time —
GET /Sessionssampled once a second over the same session returned90000000, 100000000, 110000000, 120000000, 130000000, 140000000. So the two paths now disagree with each other: a client that polls sees the position move, and a client on the socket sees it jump once per report. The dashboard is the second kind.One incidental note for whoever picks this up:
?api_key=is refused on/socketunlessenable_legacy_authorizationis on (crates/ephyra-http/src/auth.rs:194).?ApiKey=is the spelling that works with legacy auth off.Fixed in
e78c7aad, landed onmainatf0ffda81.A 1 s poll in
crates/ephyra-server/src/serve.rscallsSessions::nudge_playing. While something is advancing, it wakes the session feed without forcing a send, so each subscription's own interval throttles it as upstream'sBasePeriodicWebSocketListenerdoes. D46 records the mechanism.Measured live against upstream: a socket subscribed with
SessionsStart "0,1500", one report, then 8 s of silence. Both servers pushed 2Sessionspayloads with an advancing position. Before the change, ours pushed 0.The review found that the wake had restarted the socket's quiet timeout, which disabled the keepalive for every socket on the server while anything played. The deadline now moves only on a client message (
ac89e383). Measured: a silent socket was prompted at 0 s and 45 s and dropped at 60 s, while the feed kept waking.