PR #252 deferred task · The collector stops parsing feeds; RSSConsumer takes over parse + per-entry build + dedup.
BEFORE — collector does the thinking
AFTER — collector is a dumb pump
rss_feed typerss_feed, new shapeNo rename (Uri's call) — the message still means "an RSS feed". Stale per-entry messages still fail loudly: they lack raw_body_b64 → non-recoverable, dropped + error log.
feedparser does its own encoding detection on the original bytes. Hebrew feeds (windows-1255 etc.) make byte fidelity load-bearing — decoding server-side would corrupt it.
Per message: ONE feed_url = ANY(...) indexed SELECT pre-filters the whole window; misses go through find_or_create_feed. Stateless, exact, replica/restart-proof (~1–3 cheap queries/sec total). Replaced the in-memory SeenUrlCache — Uri's call after review.
A link counts as seen the moment its feeds row is created (Uri's call). Downstream failures are NOT silently retried — they stay visible in DB state as "link found, no article", keeping the link-found vs article-found KPIs divergent.
Title/content/date/tags parsing relocates wholesale (git mv). Entry dicts the consumer builds are field-identical to today's messages — downstream (hits, COLLECT_MORE_INFO) untouched.
execute() override (base publishes), _seen deque + constant, _create_feed_message. (Legacy RSSFeedMessage dead code: untouched — separate cleanup.)
rss-feeds depth = 0 (old consumer drains old per-entry messages)
📊 Dashboard note: rss-feeds depth now counts feeds pending parse, not entries.
Sustained growth = the parse tier lagging = add RSSConsumer capacity (the ADR's accepted cost — the consumer is the scalable tier).