Skip to main content

hls_runtime/server/
mod.rs

1//! LL-HLS origin engine (issue #663/#717 Stage 2; plan step 4): the
2//! blocking-reload + part-availability *decision* logic and playlist
3//! rendering, driven directly from a shared `media_plane::Trunk` — not a
4//! push-fed rolling-window store of its own.
5//!
6//! # Sans-IO shape
7//!
8//! Nothing here ever `.await`s or opens a socket. [`HlsOrigin`] implements
9//! [`media_plane::egress::ServedEgress`]: its
10//! [`resolve`](media_plane::egress::ServedEgress::resolve) is a poll method
11//! returning [`media_plane::egress::EgressResponse`] — `Ready`, `Await`,
12//! `BadRequest`, or `NotFound` — never blocking the caller. The only
13//! asynchrony is `media_plane::Trunk::listen`, which hands back a
14//! runtime-agnostic `event_listener::EventListener` (a plain
15//! `Future<Output = ()>`) that *any* executor can await or time out — not a
16//! `tokio::sync::watch`.
17//!
18//! # The caller-driven wait loop
19//!
20//! An async adapter (e.g. `multimux`'s Step 5 LL-HLS route) turns an `Await`
21//! into an actual wait like this — the same shape `MediaStore`'s own
22//! (now-deleted) wait loop used, unchanged in spirit:
23//!
24//! ```text
25//! loop {
26//!     let listener = trunk.listen(); // register BEFORE re-checking (no missed-wakeup race)
27//!     match origin.resolve(request, now, await_policy) {
28//!         EgressResponse::Ready { body, .. } => return Ready(body),
29//!         EgressResponse::BadRequest { .. } => return BadRequest,
30//!         EgressResponse::NotFound => return NotFound,
31//!         EgressResponse::Await { .. } => {
32//!             // caller's own bounded timeout wraps `listener.await` here
33//!         }
34//!     }
35//! }
36//! ```
37//!
38//! The blocking-reload cap is [`media_plane::egress::AwaitPolicy`]; the
39//! actual `.await`/`tokio::time::timeout` lives entirely in the adapter —
40//! this module never assumes a clock.
41//!
42//! # `std`-only
43//!
44//! Like [`media_plane::Trunk`] itself, this module needs `std::sync::Mutex`,
45//! so it is only compiled when this crate's `std` feature is enabled (the
46//! default, and the only thing that pulls in the `media-plane` dependency at
47//! all — see this crate's `Cargo.toml`). A caller building
48//! `--no-default-features` (e.g. an embedded playback-only client) gets
49//! [`crate::client`] but not `server`.
50
51mod engine;
52
53pub use engine::{
54    BlockingQuery, Container, DEFAULT_TRACK_ID, HlsBody, HlsOrigin, HlsOriginBuildError,
55    HlsOriginBuilder, HlsRequest, master_playlist_m3u8,
56};