pub trait Source: Send + Sync {
// Required methods
fn name(&self) -> &str;
fn can_serve(&self, profile: &CapabilityProfile, ref_: &Ref) -> bool;
fn fetch<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ref_: &'life1 Ref,
profile: &'life2 CapabilityProfile,
ctx: &'life3 FetchContext,
) -> Pin<Box<dyn Future<Output = Result<FetchResult, FetchError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
}Expand description
The trait implemented by every Tier 1 / 2 / 3 fetcher.
Binding signature: docs/PUBLIC_API.md §2 (NORMATIVE — the wire shape
of these three methods is semver-locked).
Required Methods§
Sourcefn name(&self) -> &str
fn name(&self) -> &str
Stable name used in metadata ([doiget].source) and provenance
rows. Conventional values: "crossref", "unpaywall", "arxiv",
"openalex", "semantic-scholar", "doaj", "tdm-elsevier",
etc. (see docs/SOURCES.md).
Sourcefn can_serve(&self, profile: &CapabilityProfile, ref_: &Ref) -> bool
fn can_serve(&self, profile: &CapabilityProfile, ref_: &Ref) -> bool
True if this source can plausibly serve the given ref under the
runtime capability profile. Implementations MUST be fast and
non-blocking; the orchestrator calls can_serve to decide whether
to invoke fetch at all.
Sourcefn fetch<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ref_: &'life1 Ref,
profile: &'life2 CapabilityProfile,
ctx: &'life3 FetchContext,
) -> Pin<Box<dyn Future<Output = Result<FetchResult, FetchError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn fetch<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
ref_: &'life1 Ref,
profile: &'life2 CapabilityProfile,
ctx: &'life3 FetchContext,
) -> Pin<Box<dyn Future<Output = Result<FetchResult, FetchError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Perform the source-specific fetch.
Implementations:
- acquire
ctx.rate_limiter.acquire(self.name()).await, - fetch via
ctx.http.fetch_bytes/ctx.http.fetch_pdf, - emit one
LogEvent::Fetchrow viactx.log.append, - return a
FetchResult.
The trait does NOT enforce these steps; it documents the protocol
so concrete impls produce uniform audit trails (per
docs/ARCHITECTURE.md §6 and docs/PROVENANCE_LOG.md §3).