pub(crate) async fn drain_honouring_release_times<S, F>(
pending: &mut PendingQueue,
send: &mut S,
cancel: &CancellationToken,
on_shape: F,
) -> Result<DrainOutcome, EgressError>Expand description
Write everything queued at its release time, racing cancellation.
The shape both release-honouring drains take — the FIN drain in the read
arm’s None branch and the one a terminal runs before it resets. Both
sit inside select! arm bodies, which are not preemptible, so writing
either as a plain while let loop would let a Hold on a gate nobody
releases pin session teardown for up to EgressConfig::max_hold —
precisely the failure the deque was chosen over a writer task to avoid.
The inner select! is biased so cancellation wins deterministically
when both are ready. Unbiased, a cancelled session could keep picking
the release branch, find nothing due, and spin.
Release lateness is not sampled here: this drain honours release times only until cancellation, and recording a teardown flush as a timing sample would report teardown as a timing failure.
§Shaping is reported here
on_shape is called once per ShapeReport the drain’s own
PendingQueue::pop_next_due produces, and it exists because this loop
is a full release seam and not a teardown flush: on a shaped queue every
pop below debits a token bucket and every clamp or expiry is decided
here. The FIN path — header, a few objects, FIN, the ordinary MoQT
subgroup shape — reaches the wire through this function and not
through release_due_units, so a drain that swallowed its reports would
apply the whole profile to the normal case and say nothing about it.
That is the silent no-op this signature exists to prevent, and the reason
the parameter is not optional: a caller cannot forget what it has to name.
Passing a no-op closure is correct only where no report can exist —
every #[cfg(test)] caller in this module builds an unshaped queue, and
an unshaped queue’s pop_next_due never reaches a scheduler.