Integrated deployments recorded no served bytes at all: BytesServed was only
ever advanced by the edge writer, so a single-node install showed
bytes_served: 0 for every stream. Worse, integrated LastServedAt was mapped
from Session.LastActivityAt, which UpdateProgress advances — letting a client
influence which of its own streams the over-cap enforcer trims first.
- internal/playback: Session gains BytesServed and a distinct LastServedAt.
LastServedAt advances only from server-observed events (AddServedBytes,
BeginTransport, EndTransport) and never from a client progress report.
LastActivityAt keeps its exact prior meaning and reaping semantics.
- internal/playback/metered_writer: one shared SessionMeteredWriter for every
integrated pour. It forwards io.ReaderFrom so the kernel sendfile path
survives, guards the fallback copy against re-entering ReadFrom, and
implements Unwrap() so the revocation cut's SetWriteDeadline still reaches
the socket. Both properties have regressed on this branch before (GAP-3,
GAP-9) and are now pinned by a chain test.
- Wired at every integrated pour: native direct-play/remux and transcode
segment, jellycompat direct/remux and HLS segment. Each site defers the tail
flush; the wrapper alone loses the final partial chunk.
- Close VERIFY-4 (buffer-ahead evasion): an unpaused transcode gets a bounded
10m grace measured from the server-observed clock. This covers local,
cleanly-completed and offloaded transcodes uniformly, unlike an ffmpeg
liveness probe, which sees only local processes and reports false once a
copy-mode encode finishes ahead of playback. Paused sessions keep their
load-bearing 30m grace.
- internal/nodesessions: the same idle window one layer out — transcode
records idle out at 180s instead of 60s, applied through a single helper
used by ActiveCount, Snapshot and refreshAll so the node's count and status
view cannot disagree.
Part of the stream monitoring & kill-switch epic.