Pruning respects a star from anyone
prune_entries still guarded on entries.flagged, which nothing writes since read state moved to entry_state -- so starring a text item with no file would not have saved it from the age sweep. It follows the reaper's rule now, and takes orphaned read state with whatever it deletes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdXho5tTkjFLeUXKbEjKBh
This commit is contained in:
19
src/db.rs
19
src/db.rs
@@ -536,14 +536,27 @@ impl Db {
|
|||||||
pub fn prune_entries(&self, older_than: i64) -> Result<usize> {
|
pub fn prune_entries(&self, older_than: i64) -> Result<usize> {
|
||||||
let conn = self.conn.lock().unwrap();
|
let conn = self.conn.lock().unwrap();
|
||||||
let n = conn.execute(
|
let n = conn.execute(
|
||||||
"DELETE FROM entries WHERE flagged = 0
|
"DELETE FROM entries
|
||||||
AND coalesce(published, first_seen) < ?1
|
WHERE coalesce(published, first_seen) < ?1
|
||||||
AND NOT EXISTS (
|
AND NOT EXISTS (
|
||||||
SELECT 1 FROM enclosures e
|
SELECT 1 FROM enclosures e
|
||||||
WHERE e.feed_id = entries.feed_id AND e.guid = entries.guid
|
WHERE e.feed_id = entries.feed_id AND e.guid = entries.guid
|
||||||
AND e.path IS NOT NULL)",
|
AND e.path IS NOT NULL)
|
||||||
|
-- Starred by anyone keeps it, the same rule the reaper follows.
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM entry_state s
|
||||||
|
WHERE s.feed_id = entries.feed_id AND s.guid = entries.guid
|
||||||
|
AND s.flagged = 1)",
|
||||||
[older_than],
|
[older_than],
|
||||||
)?;
|
)?;
|
||||||
|
// Whatever went takes everyone's read state with it, rather than leaving rows
|
||||||
|
// pointing at an item that no longer exists.
|
||||||
|
conn.execute(
|
||||||
|
"DELETE FROM entry_state WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM entries e
|
||||||
|
WHERE e.feed_id = entry_state.feed_id AND e.guid = entry_state.guid)",
|
||||||
|
[],
|
||||||
|
)?;
|
||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,11 +189,13 @@ mod tests {
|
|||||||
fn prune_keeps_entries_that_still_have_a_file() {
|
fn prune_keeps_entries_that_still_have_a_file() {
|
||||||
let db = Db::memory().unwrap();
|
let db = Db::memory().unwrap();
|
||||||
db.exec_for_test(
|
db.exec_for_test(
|
||||||
"INSERT INTO entries (feed_id, guid, first_seen, read, flagged) VALUES
|
"INSERT INTO users (id, name, is_admin, created) VALUES (1,'ray',1,0);
|
||||||
('f', 'has-file', 100, 1, 0),
|
INSERT INTO entry_state (user_id, feed_id, guid, flagged) VALUES (1,'f','flagged',1);
|
||||||
('f', 'no-file', 100, 1, 0),
|
INSERT INTO entries (feed_id, guid, first_seen) VALUES
|
||||||
('f', 'flagged', 100, 1, 1),
|
('f', 'has-file', 100),
|
||||||
('f', 'recent', 900, 1, 0);
|
('f', 'no-file', 100),
|
||||||
|
('f', 'flagged', 100),
|
||||||
|
('f', 'recent', 900);
|
||||||
INSERT INTO enclosures (id, feed_id, guid, url, path, state) VALUES
|
INSERT INTO enclosures (id, feed_id, guid, url, path, state) VALUES
|
||||||
(1, 'f', 'has-file', 'u1', '/tmp/x', 'done');",
|
(1, 'f', 'has-file', 'u1', '/tmp/x', 'done');",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user