From e130cb1dfb746f257e5ac57a1f18b013282ffa83 Mon Sep 17 00:00:00 2001 From: anonsaber Date: Wed, 30 Sep 2026 12:20:03 +0800 Subject: [PATCH] refactor: drop the never-read EmailChanges.destroyed field It was populated at the client boundary but read nowhere in production - the doc comment claimed "retained for cursor accounting", yet the cursor is just new_state. Deletions are dropped at the boundary instead of being plumbed through and then ignored one layer in. The upstream crate still returns destroyed; we simply stop carrying it. Re-add it only when something acts on deletions (e.g. pruning a dedup key) - keeping an unread Vec costs a copy on every changes page for nothing. --- src/domain/jmap.rs | 7 +++---- src/domain/jmap/client.rs | 1 - src/worker.rs | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/domain/jmap.rs b/src/domain/jmap.rs index 1c16e26..a359002 100644 --- a/src/domain/jmap.rs +++ b/src/domain/jmap.rs @@ -55,14 +55,14 @@ pub struct EmailContent { pub is_long: bool, } -/// A channel-neutral page of JMAP Email/changes. Deleted IDs are retained for -/// cursor accounting but are not notified because they have no metadata. +/// A channel-neutral page of JMAP Email/changes. Only `created` and `updated` +/// drive notification: deletions have no metadata to notify about and are +/// therefore dropped at the boundary rather than plumbed through. #[derive(Debug, Clone, PartialEq, Eq)] pub struct EmailChanges { pub new_state: String, pub created: Vec, pub updated: Vec, - pub destroyed: Vec, pub has_more: bool, } @@ -320,7 +320,6 @@ mod tests { new_state: "new".into(), created: vec!["email-1".into()], updated: vec![], - destroyed: vec![], has_more: false, }) } diff --git a/src/domain/jmap/client.rs b/src/domain/jmap/client.rs index 7961210..f92f8e5 100644 --- a/src/domain/jmap/client.rs +++ b/src/domain/jmap/client.rs @@ -172,7 +172,6 @@ impl JmapBackend for JmapClientBackend { new_state: response.new_state().to_owned(), created: response.created().to_owned(), updated: response.updated().to_owned(), - destroyed: response.destroyed().to_owned(), has_more: response.has_more_changes(), }) } diff --git a/src/worker.rs b/src/worker.rs index 88dbf9f..3feabfa 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -341,7 +341,7 @@ impl WorkerHandler for MetadataWorker { // Re-baseline instead of failing the invocation. jmap-client // 0.4.2 exposes no reset signal: `ChangesResponse` only // carries `oldState`/`newState`/`hasMoreChanges`/`created`/ - // `updated`/`destroyed`, so a `/changes` failure is + // `updated`, so a `/changes` failure is // indistinguishable from "the server no longer replays from // this `sinceState`". Returning `Err(())` leaves the cursor // untouched, so every later invocation retries the same dead