enqueue method
Admits send into the window, awaiting room first, and runs it after
every previously admitted frame has completed.
A send failure is contained: it neither breaks the chain for later
frames nor surfaces here (the transport layer owns delivery errors).
Implementation
Future<void> enqueue(Future<void> Function() send) async {
while (_outstanding >= capacity) {
final gate = Completer<void>();
_gates.add(gate);
await gate.future;
}
_outstanding++;
_chain = _chain.then((_) async {
try {
await send();
} catch (_) {
// Delivery errors belong to the transport; the stream continues.
} finally {
_outstanding--;
if (_gates.isNotEmpty) _gates.removeFirst().complete();
}
});
}