A refresh someone asks for reads the feeds in full (#77)

Check every feed, a feed's refresh, pull to refresh and ipx fetch --force
all send force, which only skipped the not-due wait: the request still
carried the stored ETag and Last-Modified, so an unchanged feed answered
304 and was not read. anil-dash got no site icon from a refresh for this
reason. A forced scan now drops the validators; the scheduled scan keeps
them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-28 23:47:08 +00:00
parent 7d55d99fac
commit bae22e553e
2 changed files with 10 additions and 2 deletions

View File

@@ -34,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
pinned: a tick when read, an envelope when not. It used to show the opposite.
- In Directory and Popular, Subscribe is a plus again, not the tick that marks a feed you have.
- A feed's refresh button looks like the buttons beside it, instead of standing out filled in.
- Refreshing reads your feeds in full, instead of only asking each one whether it changed, so
a feed that has not changed is still read again.
- A web page with some non-ASCII characters no longer hides the feed it links, or crashes looking for it.
- Pulling the item list down to check for new items shows a spinner for a couple of seconds, and
a second pull meanwhile does nothing, instead of no sign at all that the check started.

View File

@@ -48,7 +48,7 @@ enum Command {
Fetch {
/// Only this feed id
feed: Option<String>,
/// Poll even when the feed is not due yet
/// Read the feed in full now, even when it is not due and has not changed
#[arg(long)]
force: bool,
},
@@ -921,7 +921,13 @@ async fn fetch(ctx: &Arc<Ctx>, only: Option<&str>, force: bool, scope: &[String]
};
for sub in subs.iter().filter(|s| only.is_none_or(|o| o == s.id) && in_scope(s)) {
let (id, feed_cfg) = (&sub.id, &sub.cfg);
let state = ctx.db.http_state(id).await?;
let mut state = ctx.db.http_state(id).await?;
// A scan someone asked for reads the feed in full. With the validators it only skipped the
// wait: a feed that had not changed answered 304 and nothing was read (#77).
if force {
state.etag = None;
state.last_modified = None;
}
if !force && let Some(last) = state.last_checked {
let due = last + due_after(&cfg, feed_cfg, state.ttl_mins) as i64;