Expand description
Feed fetch → parse → sanitize → store pipeline.
This is the module that turns a feed URL into rows in the store. It is
deliberately conservative on three axes, because a feed reader ingests
hostile, arbitrary web input:
- Politeness — fetches use a conditional GET (
If-None-Match/If-Modified-Sincefrom the storedETag/Last-Modified), an identifiablecrate::USER_AGENT, a request timeout, and a simple exponential backoff hint on error. A304 Not Modifiedis a no-op: the feed is untouched apart from bumping its next-poll time. - Safety — every entry’s HTML is run through
ammoniabefore it is ever stored. Scripts, event handlers,javascript:URLs, tracking pixels’ dangerous attributes, and other XSS vectors are stripped. Feeds carrying<script>is not hypothetical; treat all feed HTML as untrusted. The reader does not rely on this alone: it re-cleans the stored body with the samesanitize_htmlat render, throughcrate::sanitized_html::SanitizedHtml(#151). - Robustness — a malformed feed is logged and skipped, never a
panic. One bad publisher must not take down the poller. All non-test
paths use
Result/anyhow; there are nounwrap/expects.
The normalized shape written to the store is the store’s own
store::NewFeed / store::NewEntry; dedup is by feed-native GUID via
store::insert_entries’s ON CONFLICT (feed_id, guid) upsert.
Structs§
- Starvation
- Whether ingest is being starved of sanitize permits, for
/statsand the logs (review of #274).
Enums§
- Failure
Kind - Why a poll failed, as a closed set.
- Feed
Kind - What the poller does with a feed row.
- Feed
Privacy - The privacy classification of a feed URL — the output of
classify_feed_privacy. - Poll
Outcome - The outcome of polling a single feed. Lets the scheduler decide how to reschedule (and lets tests assert what happened) without inspecting the DB.
Constants§
- MAX_
FAILURE_ DETAIL_ CHARS - Cap on a failure detail, applied where the string is BUILT.
- STARVED_
ALERT_ SECS - After this long without a free permit, a deferral logs at error level.
Statics§
- SANITIZE_
STARVATION - The production
Starvation, which/statsreads.
Functions§
- backoff_
for - Compute the backoff for the
nth consecutive failure (1-based), clamped toBACKOFF_MAX. Exponential in the error count so transient blips retry soon while a durably-broken feed backs off toward daily. - build_
client - Build a
reqwest::Clientconfigured for polite and safe feed fetching. - classify_
feed_ privacy - Classify whether a feed URL carries a secret credential in the URL itself.
- discover_
feed - Discover a feed URL from a site’s HTML via
<link rel="alternate" type="application/rss+xml|atom+xml" href="…">. - failure_
detail - Render an error chain into a bounded
PollOutcome::Faileddetail. - is_
storable_ feed_ url - Whether a URL may be stored or published as a feed URL at all.
- poll_
feed - Fetch, parse, sanitize, normalize, and store a single feed.
- poll_
feed_ by_ kind - Poll one feed by what it is: an RSS/Atom/JSON document over HTTP, or a standard.site publication read from its author’s PDS.
- poll_
publication_ group - Read several publications from one repo with one walk of its documents
(
standard_site::fetch_repo), and store each. One outcome per feed, in order. The caller groups by repo; a feed from another repo, or one whose URL is not a publication URI, gets its own failure and does not affect the rest. - settle_
poll - Apply a
PollOutcometo the feed’s row: settle the error columns AND reschedule it. Both halves, always, from one place.