feat: local delete with seen marking for reader-side removal
This commit is contained in:
parent
234b75651f
commit
1ae2752eb0
1 changed files with 35 additions and 0 deletions
|
|
@ -571,6 +571,23 @@ impl Store {
|
||||||
.is_some())
|
.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes one message from the local store — the reader's delete, which
|
||||||
|
/// the server-side DELETE (sec 6.1) knows nothing about. The id is marked
|
||||||
|
/// seen (sec 10), so a copy still sitting on the server is fetched again
|
||||||
|
/// without being re-stored: deleting locally must not resurrect the
|
||||||
|
/// message on the next fetch.
|
||||||
|
pub fn delete_local(&self, folder: &str, id: &[u8; ID_LEN]) -> Result<(), Error> {
|
||||||
|
let table = match folder {
|
||||||
|
"sent" => "sent",
|
||||||
|
_ => "inbox",
|
||||||
|
};
|
||||||
|
self.db()
|
||||||
|
.execute(&format!("DELETE FROM {table} WHERE id = ?1"), params![id])?;
|
||||||
|
self.db()
|
||||||
|
.execute("INSERT OR IGNORE INTO seen (id, at) VALUES (?1, ?2)", params![id, now()])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// One folder, ordered by arrival or sending time. `folder` is "inbox",
|
/// One folder, ordered by arrival or sending time. `folder` is "inbox",
|
||||||
/// "requests", "sent" or "all".
|
/// "requests", "sent" or "all".
|
||||||
pub fn mail(&self, folder: &str) -> Result<Vec<Stored>, Error> {
|
pub fn mail(&self, folder: &str) -> Result<Vec<Stored>, Error> {
|
||||||
|
|
@ -887,6 +904,24 @@ mod tests {
|
||||||
assert!(store.history("b@example.org").unwrap().is_empty());
|
assert!(store.history("b@example.org").unwrap().is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn local_delete_marks_seen_so_a_refetch_does_not_restore() {
|
||||||
|
let store = temp_store("delete-local");
|
||||||
|
let id = [3u8; 32];
|
||||||
|
store.store_inbox(&id, b"envelope", 100, false, true).unwrap();
|
||||||
|
store.delete_local("inbox", &id).unwrap();
|
||||||
|
assert!(store.mail("all").unwrap().is_empty());
|
||||||
|
// Sec 10: the id is seen, so the fetch pipeline will not re-store
|
||||||
|
// the still-kept server copy. (The dedupe is the pipeline's seen
|
||||||
|
// check, not store_inbox's — a direct insert is a caller override.)
|
||||||
|
assert!(store.seen(&id).unwrap());
|
||||||
|
// Sent copies delete locally too, with the same protection.
|
||||||
|
let sent_id = [4u8; 32];
|
||||||
|
store.store_sent(&sent_id, "bob@example.org", b"sent", 50).unwrap();
|
||||||
|
store.delete_local("sent", &sent_id).unwrap();
|
||||||
|
assert!(store.mail("sent").unwrap().is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn in_memory_store_round_trips() {
|
fn in_memory_store_round_trips() {
|
||||||
let store = Store::open_in_memory().expect("memory store opens");
|
let store = Store::open_in_memory().expect("memory store opens");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue