pub struct UpstreamRefused { /* private fields */ }Expand description
Typed sentinel for an upstream refusing delivery up front — a
StreamResponse with body.ok == false (#1144). Carries the wire
StreamError verbatim (mirroring UpstreamVoucherRejected’s typed
reason, not a lossy stringification) so the pull orchestrator can
downcast_ref and give each refusal the verdict it deserves, rather than
folding every one into “unreachable”.
That distinction is the whole point. A refusal is proof the peer is reachable and answering, so no class is evidence that it is degraded (ADR 005 §Open-time refusal classes):
NotFound— “not now”. It is NODE-scoped, not blob-scoped (ServeRejectReason::wire_errorcollapses a miss, a load shed, and several pool and signer states onto it), so it earns only a short suppression.Declined— “not this hash during this fetch”, DURABLE for this (peer, hash): asking again soon gets the same answer, so the consumer drops the peer for the hash rather than burning a candidate slot on it.Unfunded— “not at the requester’s current funding”. It says nothing about the peer; it counts toward the requester’s funding recovery.VoucherRejected— a payment fault on this lane. Listed because it genuinely arrives here: it is the code designated for MID-stream, and the mid-stream receive arms wrap anyStreamErrorinto this sentinel (#1145 review).
node_origin::classify_refusal is the consumer and matches this exhaustively, so a new
wire code breaks that build rather than silently inheriting a verdict.
Only the wire class is recoverable here, never the finer server-side
ServeRejectReason — that collapse is intentional and must not be reversed.
Display keeps the stable delivery refused: {code} text that logs, the CLI’s
cache-miss annotation, and the loopback tests match on.
The two refusal shapes are a private inner enum, not pub variants: enum
variant fields cannot be made private, so exposing them would let any caller
build an Open { .. } directly and bypass the crate-private open
constructor’s error-from-response derivation — reintroducing exactly the
doc-comment-only invariant this type exists to remove (#1377). The newtype
keeps the only paths to a value the two constructors, so the “present response
⇒ open-stage, verified” invariant is a property of the type rather than a
convention.
Implementations§
Source§impl UpstreamRefused
impl UpstreamRefused
Sourcepub const fn mid_stream(error: StreamError) -> Self
pub const fn mid_stream(error: StreamError) -> Self
Build the refusal for a mid-stream ClientMessage::StreamError
frame — the refusal that arrives after the open stage, in reply to a
delivery chunk or a voucher.
Such a frame carries no signature (#1042), so Self::evidence is None
here by construction and this is the only place that decision is made.
The four mid-stream receive sites route through it so none can drift into
synthesising a StreamResponse — which would hand an observer an unsigned
artifact the evidence contract promises always recovers to the delivering
node (#1378). The open-stage counterpart is the crate-private open.
Public because callers outside the crate (and their tests) legitimately
build mid-stream refusals; it is safe to expose precisely because it
cannot carry a signed response — the encapsulation that matters guards
the attributable open (Self::evidence), which stays crate-private
so a caller cannot mint a refusal attributed to an operator.
Sourcepub const fn error(&self) -> &StreamError
pub const fn error(&self) -> &StreamError
The wire code the upstream signed. Always a StreamError as it appeared
on the wire — never a server-side ServeRejectReason, whose seven-way
collapse onto NotFound is deliberate and one-way
(handlers::client::wire_error). Total over both shapes.
Sourcepub fn evidence(&self) -> Option<&StreamResponse>
pub fn evidence(&self) -> Option<&StreamResponse>
The upstream’s own signed StreamResponse, present iff the refusal
arrived at the open stage. None for a mid-stream frame.
An attributable record, not loose diagnostics — already verified against
expected_signer by verify_response before this value is built, so a
present value always recovers to expected_signer: the operator address
the caller bound this pull to, which is what SlashJudge._checkRegistered
resolves nodeId against.
Note it is not by itself slash evidence — no offense admits a refusal
(ok == false) as its stream leg (ADR 014). What it gives the caller is a
non-repudiable statement of why the pull was declined, signed by the
operator and usable verbatim, with no re-signing.
Trait Implementations§
Source§impl Clone for UpstreamRefused
impl Clone for UpstreamRefused
Source§impl Debug for UpstreamRefused
impl Debug for UpstreamRefused
Source§impl Display for UpstreamRefused
impl Display for UpstreamRefused
Source§impl Error for UpstreamRefused
impl Error for UpstreamRefused
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Auto Trait Implementations§
impl Freeze for UpstreamRefused
impl RefUnwindSafe for UpstreamRefused
impl Send for UpstreamRefused
impl Sync for UpstreamRefused
impl Unpin for UpstreamRefused
impl UnsafeUnpin for UpstreamRefused
impl UnwindSafe for UpstreamRefused
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> MaybeSend for Twhere
T: Send,
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.