#[non_exhaustive]pub enum AttemptOutcome {
Disabled {
env: &'static [&'static str],
},
NotApplicable,
WrongPublisher {
detail: String,
},
NotNeeded,
NoRecord,
NotOpenAccess {
detail: String,
},
Denied {
denial: DenialContext,
},
Failed {
detail: String,
},
Resolved,
}Expand description
Why a given optional source did or did not contribute.
The distinction this type exists to make: “we asked and it had
nothing” is not the same failure as “we never asked”. Before this,
both looked identical from outside — a DOI fetch that failed returned
the Crossref error and said nothing about the rest of the chain, so a
user could not tell whether HAL had been consulted and come up empty,
or whether DOIGET_ENABLE_HAL was simply unset. One means the paper is
not there; the other means you have not turned the source on. They need
completely different actions.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Disabled
Runtime flag unset — not consulted. Carries the env var so the message can name the exact thing the user has to change.
Fields
env: &'static [&'static str]Every variable that has to be set, e.g.
["DOIGET_ENABLE_HAL"] or
["DOIGET_KEY_APS", "DOIGET_AGREE_TDM_APS"].
A list rather than a string because Tier 3 needs two, and
joining them into "A + B" put a separator on the #459 wire
that a consumer would have had to split on — which is the
thing the detail() / wire() split exists to avoid (#470).
NotApplicable
This source cannot serve this kind of ref at all (e.g. an arXiv id handed to a DOI-only resolver). Not a misconfiguration.
WrongPublisher
Not consulted. A publisher-specific Tier-3 source was asked about a DOI its publisher did not register (#442).
Distinct from Self::Disabled on purpose: the credentials are
fine and there is nothing for the user to switch on. Telling them
to set DOIGET_KEY_APS because an Elsevier DOI did not resolve
would send them after the wrong problem.
NotNeeded
An earlier source in the chain already answered, so this one was deliberately skipped. Not a failure.
NoRecord
Consulted. The source has no record for this ref.
NotOpenAccess
Consulted. A record exists but is not open access — the source knows the paper and still cannot give it to us.
Denied
Consulted, and refused by a policy control with a structured reason: a redirect off the allowlist, an insecure redirect, an oversized body, a not-a-PDF (ADR-0023).
Distinct from Self::Failed because the DenialContext is what
crate::remediation::for_denial consumes. PdfLegStatus::Blocked
kept it end to end and the MCP layer turned it into a remediation;
per-source rows flattened the same information to prose, so the
richest and most actionable case degraded to text on a wire that
#459 advertises as machine-readable (#470).
Fields
denial: DenialContextThe structured denial, verbatim.
Failed
Consulted. The request itself failed (transport, auth, schema).
Resolved
Consulted, and it answered.
Implementations§
Source§impl AttemptOutcome
impl AttemptOutcome
Sourcepub fn was_consulted(&self) -> bool
pub fn was_consulted(&self) -> bool
Whether a request actually went out for this source.
This is the predicate the reachability tests assert on: a source
reporting was_consulted() == false is one the production path
never reached, which is exactly the condition that used to be
invisible.
Sourcepub fn wire(&self) -> &'static str
pub fn wire(&self) -> &'static str
Stable machine token for this outcome (#459).
Self::render is prose and may be reworded; this is the thing a
consumer branches on. Kept separate for that reason — the CLI has
already reworded the trace twice (#413, #438) and a caller keying
off the sentence would have broken both times.
The two halves of the vocabulary mirror Self::was_consulted:
not_consulted_* means no request went out, consulted_* means one
did. That distinction is the entire reason this type exists.
Sourcepub fn detail(&self) -> Option<&str>
pub fn detail(&self) -> Option<&str>
The variant’s free-text payload, when it has one.
Carried separately from Self::wire so a consumer gets the
actionable specifics — which env var, which prefix, which error —
without parsing them back out of the rendered sentence.
Sourcepub fn required_env(&self) -> Option<&'static [&'static str]>
pub fn required_env(&self) -> Option<&'static [&'static str]>
The variables a Disabled row needs set, in the order the user
should set them. None for every other outcome.
Sourcepub fn denial(&self) -> Option<&DenialContext>
pub fn denial(&self) -> Option<&DenialContext>
The structured denial behind a Denied row, which is what
crate::remediation::for_denial takes. None otherwise.
Trait Implementations§
Source§impl Clone for AttemptOutcome
impl Clone for AttemptOutcome
Source§fn clone(&self) -> AttemptOutcome
fn clone(&self) -> AttemptOutcome
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AttemptOutcome
impl Debug for AttemptOutcome
impl Eq for AttemptOutcome
Source§impl PartialEq for AttemptOutcome
impl PartialEq for AttemptOutcome
Source§fn eq(&self, other: &AttemptOutcome) -> bool
fn eq(&self, other: &AttemptOutcome) -> bool
self and other values to be equal, and is used by ==.