Expand description
The one place an Action becomes bytes on the wire, or a refusal.
§Why this module exists at all
Everything the engine can do is already published, by draft and by site,
in crate::capability. This module’s whole job is to not re-derive
any of it: every admission decision here goes through
crate::capability::classify, the same function
Capabilities::supports
publishes, so the table a caller reads before a run and the code
that runs it are literally the same code. A cell that the table calls
No(WrongSite { .. }) is refused here with the refusal value classify
returned, not with one this file rebuilt from the Action it was
handed.
That last distinction is load-bearing and easy to lose. At
Site::Object both ActionKind::Replace and
ActionKind::ReplaceObject classify to the same value —
No(WrongSite { site: Object, action: ActionKind::ReplaceObject }) —
because Action::Replace(b) is the one action value that attempts both
kinds at once. If this file synthesized WrongSite { action: Replace } from the value it saw, the published ReplaceObject cell would
become unassertable by tests/action_matrix.rs, which compares
refusal == r. The ProxyEvent::ActionRefused event’s separate
action field still reports what the value was — Replace — because
that is what the hook returned; only refusal is the table’s.
§Which refusals are this module’s to produce
Three, and they are the three that depend on the action’s payload or on
session state rather than on the (site, kind) pair:
Refusal::WrongComposition— what aAction::Delay/Action::Holdwrapped;Refusal::ErrorCodeOutOfRange— a stream error code above the QUIC varint ceiling;Refusal::SessionAlreadyClosing— a secondAction::CloseSession.
Everything else is propagated from classify. The table-only
refusal Refusal::StreamNotFramed is never emitted from here —
every_refusal_this_module_emits_is_classifys_or_one_of_its_own_three
below is the falsifiable form of that claim: it sweeps fourteen drafts ×
five sites × thirteen action shapes and asserts that neither variant ever
reaches an ActionRefused, and that all three executor-owned refusals do.
§Event cardinality — what this module guarantees
- Every refusal emits exactly one
ProxyEvent::ActionRefusedand bumpsCounters::actions_refusedexactly once. The two happen in one function (Reporter::refused) so they cannot drift, and the counter is bumped even when the observer is detached — a run with no observer still counts its refusals. - Every applied action emits exactly one
ProxyEvent::ActionAppliedper phase. - Every transport failure on an admitted action emits exactly one
ProxyEvent::ActionFailed, throughReporter::failed. This module does not own the transport, so the caller makes that call; it is the only shape of report this module publishes rather than performs.
§Delay { then: Replace } — two events, and this is the ruling
Nothing about the action shape forces the choice, so it is written down
here. It is two ProxyEvent::ActionApplied events, distinguishable
by their action field:
- at the decision:
{ action: Delay, effect: Queued { release_at } }— the modifier was accepted and the unit is in the queue; - at the release:
{ action: Replace, effect: Replaced { bytes } }— the wire actually changed.
One event would force a choice between reporting the deferral and reporting
the effect, and a queued unit lost at teardown would have reported a
Replaced that never happened. Two keep the engine accepted this and
“the wire changed” separately falsifiable, which is exactly what
ImpairmentKind::QueuedBytesAtTeardown is paired against. Stated as the
rule a test can count: one ActionApplied for a direct action, two for a
Delay/Hold.
The second event is owed by this module and paid by the caller, because
the release happens in session.rs’s select! arm long after execute
returned. DeferredEffects is the ledger: execute pushes exactly one
entry per PendingQueue::push and the caller pops exactly one per
released unit, then hands it to Reporter::applied_deferred. Entries
are Option because a direct action queued merely for ordering (a
Pass behind a delayed unit) reports once at the decision and owes
nothing at release.
Units a drain could not flush report nothing further — that absence
is the designed pairing with QueuedBytesAtTeardown, not a lost event.
See DeferredEffects for the three-call discipline.
Structs§
- Applied
Plan 🔒 - An admitted action, before its event is emitted.
- Content 🔒
- What a content action makes of the unit — the four things a
Action::Delay/Action::Holdmay wrap, and the same four when they stand alone. - Deferred 🔒
- What a released unit owes the observer.
- Deferred
Effects 🔒 - The
ProxyEvent::ActionAppliedevents owed at release, in queue order. - Engine 🔒
- Everything
executemay mutate. - Outcome 🔒
- Everything one
executecall decided. - Queue 🔒
- The per-stream deferral state.
- Refused 🔒
- A refusal, and the kind to name in the event.
- Reporter 🔒
- Where this module’s events and counters go.
- Unit 🔒
- One unit of traffic, at one site, at one instant.
Enums§
- Payload 🔒
- The bytes a content action produced, or their absence.
- Plan 🔒
- The wire operation
executehas decided on but not performed. - Stream
Site 🔒 - Which of the two
StreamActionsites a decision was taken at. - Target 🔒
- The unit an
Actionwas returned for, with every factcrate::capability::classifyneeds to judge it.
Constants§
- MAX_
APPLICATION_ 🔒ERROR_ CODE - The QUIC varint ceiling,
2^62 - 1. - NESTED_
MODIFIER 🔒 - WRAPPED_
CLOSE 🔒 - WRAPPED_
TERMINAL 🔒
Functions§
- admit 🔒
- The five verdicts, as an admission decision.
- admit_
conditional 🔒 - What a surviving
Support::Conditionalmeans at execution time. - admit_
kind 🔒 - Ask
crate::capability::classify, and turn its verdict into an admission. - check_
composition 🔒 - Composition: a modifier accepts only a content action.
- check_
error_ 🔒code - A stream application error code must fit a QUIC varint.
- commit_
now 🔒 - Write now, or take an ordering slot behind what is already waiting.
- elide_
renumbers_ 🔒successor - Whether eliding this object leaves the framer owing a successor fix-up.
- enqueue_
unshown 🔒 - Queue bytes the hook was never shown, on a shaped stream.
- execute 🔒
- Execute one
Actionat one site. - execute_
stream 🔒 - Execute one
StreamAction, atSite::StreamOpenorSite::StreamHeader. - forward_
unchanged 🔒 - The refusal path’s write: the unit goes out unchanged, through the same
fork an admitted
Action::Passtakes. - kind_of 🔒
- The
ActionKindanActionvalue attempts. - pending_
for 🔒 - plan_
action 🔒 - prepare_
content 🔒 - Classify and realise one content action.
- push_
unit 🔒 - Push one unit and record exactly one ledger entry against it.
- queue_
config 🔒 - The queue’s knobs, or the defaults when there is no queue.
- shape_
elide 🔒 - Run the elide guards for a shaper’s tail-drop, and say whether the unit may be discarded.
- stream_
reset_ 🔒code_ defined - Whether the draft defines a stream-reset error code vocabulary.