Poll subscribed feeds for new articles on a schedule #5

Merged
claude-bot merged 2 commits from worktree-feed-polling into main 2026-09-03 14:07:27 +00:00
Collaborator

Summary

  • Feed subscriptions were already persisted (feeds table), but nothing ever re-fetched them after the initial subscribe — scoring.rs had a TODO where feed polling was supposed to go.
  • Adds feed_polling::run, wired into the scheduler: runs once at startup (so reopening the app catches up on new articles immediately) and every 15 minutes thereafter, ahead of the scoring pass.
  • Adds Db::list_feeds and Db::mark_feed_fetched. New-article dedup relies on the existing articles.url unique constraint (insert_article already does on_conflict_do_nothing), so re-fetching a feed and re-inserting already-seen entries is a no-op.
  • A feed that fails to fetch (dead URL, parse error) logs a warning and is skipped for that cycle rather than aborting the whole poll.

Test plan

  • cargo build --workspace
  • cargo clippy --workspace --all-targets (clean)
  • cargo fmt --check
  • cargo test --workspace

🤖 Generated with Claude Code

https://claude.ai/code/session_01QmwX8eafbMstJvt8XPSqft

## Summary - Feed subscriptions were already persisted (`feeds` table), but nothing ever re-fetched them after the initial subscribe — `scoring.rs` had a TODO where feed polling was supposed to go. - Adds `feed_polling::run`, wired into the scheduler: runs once at startup (so reopening the app catches up on new articles immediately) and every 15 minutes thereafter, ahead of the scoring pass. - Adds `Db::list_feeds` and `Db::mark_feed_fetched`. New-article dedup relies on the existing `articles.url` unique constraint (`insert_article` already does `on_conflict_do_nothing`), so re-fetching a feed and re-inserting already-seen entries is a no-op. - A feed that fails to fetch (dead URL, parse error) logs a warning and is skipped for that cycle rather than aborting the whole poll. ## Test plan - [x] `cargo build --workspace` - [x] `cargo clippy --workspace --all-targets` (clean) - [x] `cargo fmt --check` - [x] `cargo test --workspace` 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QmwX8eafbMstJvt8XPSqft
claude-bot added 1 commit 2026-09-03 11:20:50 +00:00
Poll subscribed feeds for new articles on a schedule
All checks were successful
CI / check (pull_request) Successful in 13m50s
CI / test (pull_request) Successful in 4m15s
CI / audit (pull_request) Successful in 15s
6fb470084d
Feeds were already persisted, but nothing ever re-fetched them after
the initial subscribe — scoring.rs had a TODO where feed polling was
supposed to go. Add a feed_polling job that re-fetches every
subscribed feed, relies on articles.url's unique constraint to skip
ones already seen, and stamps last_fetched_at. Runs once on startup
(so reopening the app catches up immediately) and every 15 minutes
after, ahead of the scoring pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QmwX8eafbMstJvt8XPSqft
schaefera added 1 commit 2026-09-03 11:45:57 +00:00
Merge remote-tracking branch 'origin/main' into worktree-feed-polling
All checks were successful
CI / check (pull_request) Successful in 1m35s
CI / test (pull_request) Successful in 3m8s
CI / audit (pull_request) Successful in 13s
64c46655d7
# Conflicts:
#	crates/db/src/lib.rs
claude-bot merged commit 088821f660 into main 2026-09-03 14:07:27 +00:00
claude-bot deleted branch worktree-feed-polling 2026-09-03 14:07:27 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: schaefera/feedsignal#5
No description provided.