Workflow status is tracked in GitHub. This local document is retained as an engineering spec/evidence record.
RUST-FEAT-007 - REST push: Server-Sent Events stream for live transfer updates¶
Summary¶
Add a push path to /api/v1 so a controller (TrackMuleBB) gets transfer state
changes without polling. Expose GET /api/v1/events as a text/event-stream
(Server-Sent Events) that emits transfer change events (add / update / remove),
and advertise the transfers.sse capability via GET /capabilities. The existing
GET /api/v1/transfers full-poll stays as the baseline + fallback.
SSE is chosen over WebSocket because the dashboard need is unidirectional
server -> client: commands (pause/resume/add) already flow through normal REST
POSTs, so a bidirectional socket would be pure overhead. SSE is plain HTTP,
reuses the X-API-Key header, and supports resume via Last-Event-ID.
Why This Matters¶
/transfers re-serializes the whole list every poll; push delivers only changes,
near-instantly, and scales with churn rather than library size. emulebb-rust is
already event-driven internally (it is the source of truth), so the events exist —
this just surfaces them.
Intended Shape¶
GET /api/v1/events->text/event-stream; each event carries a monotonically increasing id and a JSON payload of the changed transfer(s) (same field shape as theTransferDTO) plus aremovedform keyed by hash.- Internal Tokio
broadcastbus: the transfer manager publishes change events; the SSE handler fans them out to subscribers. Periodic heartbeat/comment line to keep the connection alive through proxies. - Resume: honour
Last-Event-ID(replay-from or signal "re-baseline via/transfers"). Auth unchanged (X-API-Key). GET /capabilitiesadvertisestransfers.sseso a controller gates on it and falls back to poll when absent.- (Considered, not chosen) a delta-pull
GET /api/v1/sync?rid=Nmirroring qBittorrent's/sync/maindata; recorded as the lower-effort alternative if a long-lived stream is undesirable.
Acceptance Criteria¶
- [ ]
GET /api/v1/eventsstreams add/update/remove transfer events as SSE with incrementing event ids; survives a quiet period via heartbeats. - [ ]
Last-Event-IDeither replays missed events or instructs a/transfersre-baseline; no silent gaps. - [ ]
GET /capabilitiesliststransfers.sse;/transfersis unchanged. - [ ] Auth via
X-API-Key; contract version (x-contract-version) bumped.
Notes¶
- RC2 soft-freeze: this is a forward-lineage
/api/v1contract addition, not a parity/release-blocking fix. Design now, schedule after the freeze (the backlog explicitly stages design work; emulebb-rust is out of RC2 ship scope). - Controller side: trackmulebb TMBB-FEAT-014 (capability-gated push adapter,
poll fallback). qBittorrentBB has no SSE; its push-ish path is the
/sync/maindatadelta (trackmulebb TMBB-FEAT-005) — both unify behind one adapter abstraction.