Skip to main content

FeedKind

Enum FeedKind 

Source
pub enum FeedKind {
    Rss,
    Publication,
    Unsupported,
}
Expand description

What the poller does with a feed row.

A column, not a predicate. “Can this be fetched?” used to be substr(url, 1, 5) = 'at://' spliced into four statements, with a fifth reader that had already drifted from them. Deciding it once, in Rust, at insert — and storing the answer — means SQL cannot disagree with the fetcher, and wiring the standard.site reader becomes a change to this function plus a dispatch, rather than an edit to every statement that mentions a URL.

Variants§

§

Rss

An RSS/Atom/JSON feed document fetched over http(s).

§

Publication

An at://…/site.standard.publication/… record pair in somebody’s PDS, read by standard_site and pollable since 0.4.0.

§

Unsupported

Any other at:// row: another collection, or a spelling the storage guard would refuse. Rows like this predate that guard. Never pollable — handing one to the standard.site reader would fail its collection check every tick and publish it as an unreachable publisher — and counted as unpollable so the capacity it holds stays visible.

Implementations§

Source§

impl FeedKind

Source

pub const POLLABLE: &'static [FeedKind]

The kinds the scheduler may select: RSS, and since 0.4.0 standard.site publications. FeedKind::Unsupported is the kind it never selects.

This is the canonical home of the exclusion; the other sites point here. It used to be a SQL string predicate in store, carrying its own copy of the rule — which is how one reader (count_feeds) came to drift from it unnoticed.

Why an unpollable kind is skipped rather than failed: an Unsupported row names nothing either reader can fetch — another collection, a handle, a non-canonical spelling — so polling it could only fail. Handing such a row to the poller does not leave the feature dormant — it manufactures one permanent failure per row, which the public cause histogram then reports as an unreachable publisher. Unsupported is not broken, and telling those apart is the entire reason a failure cause is recorded. (Rows like this exist: subscriptions written by other clients before this reader refused the scheme.)

store::count_feeds is deliberately NOT filtered by this. The global ceiling bounds storage on a small box, and an unpollable row occupies a row, so it counts against the cap. An earlier version of this note listed the readers without naming the exception, which read as completeness it did not have: a review found the ceiling consuming capacity that appeared on no surface, since /stats measures the poller and excludes these rows. /admin/metrics renders store::unpollable_feeds for exactly that reason. Adding a kind here makes a population of rows due all at once. store::due_feeds orders next_poll IS NOT NULL, next_poll ASC, so a row with no scheduled poll sorts ahead of every dated one. Rows that were never pollable have no schedule, so the boot that reclassifies them hands the poller a block of N rows that outrank every regular feed until they drain — ceil(N / batch) ticks, measured, during which /stats shows a climbing backlog and nothing logs why. Bounded and harmless at ninety feeds; not at ten thousand. Whoever wires the next kind should seed or stagger next_poll for the rows it admits.

Source

pub const AGED: &'static [FeedKind]

The kinds whose entries the retention window applies to.

Age is the wrong retention policy for an archive, and that is a measurement, not a preference. Three real publications, read through standard_site::fetch on 2026-09-27: Standard.site’s newest document was 131 days old, Annotated’s 109 (with its oldest at 373), and minus listens’ 241. Against the instance default window of 14 days, every one of them stored zero rows — a green poll, an empty feed, and an info log as the only trace. Long-form publishing is not news-paced.

So a publication is bounded by COUNT instead: max_entries_per_feed in insert_entries, which caps a feed at the newest N plus up to N starred. That is a real bound — it is what keeps this from being “retention off” — and it is the one that suits a source whose value is its archive.

A generous absolute ceiling still applies (publication_retention_days), because “not aged out” must not mean “immortal”: rows belonging to a feed nobody polls any more would otherwise never be reaped at all, and the per-feed trim only runs when a poll stores something.

Source

pub fn as_str(self) -> &'static str

The column value. Stable — it is persisted.

Source

pub fn parse(raw: &str) -> Option<Self>

A closed vocabulary on the way back in: a kind written by a newer build is not silently read as one this build knows.

Source

pub fn of(url: &str) -> Self

What a URL will be stored as. The only place the question is asked.

store::feeds.kind is a cache of this function, re-derived from the URL on every start and on every upsert, so a change here needs no migration and SQL cannot hold an opinion of its own about what a row is.

Case-insensitive on purpose. An earlier version was case-sensitive, with a test pinning that a mixed-case At:// row IS handed to the poller — reasoning that if Rust does not call it an at-URI, neither should anything else. That was wrong in the direction that matters: URL schemes are case-insensitive, so Url::parse folds At:// to scheme at and net::check_scheme refuses it (the DID form does not parse at all). The row could only fail, every tick, forever, and be published in the fetch bucket as an unreachable publisher. Storing a non-canonical spelling is separately refused, because feeds.url is UNIQUE.

Trait Implementations§

Source§

impl Clone for FeedKind

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for FeedKind

Source§

impl Debug for FeedKind

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for FeedKind

Source§

impl PartialEq for FeedKind

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for FeedKind

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more