Repository navigation
Description
Leftovers from #1884 (PR #1891): minor review findings and plan items deferred by the loop.
- plan-1 (minor, plan out of scope,
mailcore/src/sync/outbox.rs:33): mailcore: Move/MarkRead/SetFlag/SetCategories ops push a draft's local: id to Graph - plan-2 (minor, plan out of scope): mailcore: check calendar events for mailcore: a draft stays addressable by its local: id after reconcile_id #1884's stale local: id after reconcile_event_id
- plan-3 (minor, plan out of scope,
mailcore/src/sync/outbox.rs:52): mailcore: a retried SendDraft re-uploads its attachments - plan-4 (minor, plan out of scope): mailcore: a queued SaveDraft of a deleted never-synced draft quarantines instead of dropping
- plan-5 (minor, plan out of scope,
mailcore/src/store/mod.rs:536): mailcore: set busy_timeout on the store's connections
plan-1
SyncCommand::Move/MarkRead/SetFlag/SetCategories addressed with a draft's local: id still push that id to Graph (OutboxOp::Move { id: local } etc. → /me/messages/local:… → 4xx → quarantine → full reconverge). Since #1884 the store-side optimistic writes (move_message) resolve a reconciled local: id, but the queued ops do not. Pre-existing for any local: id. Resolve with Store::current_id in apply_op (as Delete does since #1884), and skip a still-local: id.
plan-2
Calendar events have the same local: → Graph id shape as drafts (Store::reconcile_event_id, OutboxOp::CreateEvent/UpdateEvent/DeleteEvent). An edit window left open across a CreateEvent drain may hold the local: id after reconcile, so a later UpdateEvent { local: } would not find the event (as #1884 was for drafts). Unconfirmed: check whether any caller keeps the id, and if so apply #1884's local_id resolve to events.
plan-3
OutboxOp::SendDraft uploads every outbound attachment, then sends (mailcore/src/sync/outbox.rs). If the send fails after the uploads (a 5xx/429/transport error), the op stays queued and the retry uploads every attachment again, so the delivered message carries duplicates. Pre-existing, for Graph ids too. Record uploaded attachments (or list the draft's attachments on Graph) and skip those already there.
plan-4
A SaveDraft { local: } (or SendDraft) still queued when its never-synced draft is deleted locally fails "no local draft stored for local:…" until it is quarantined after MAX_OP_ATTEMPTS, which clears every delta link and forces a full re-sync. A draft op whose local: id resolves to no row could be dropped as a no-op instead (as Delete of an unresolved local: id is since #1884).
plan-5
The mail store is opened on two connections (the UI's and the sync thread's) and neither sets busy_timeout, so a write that meets the other connection's write lock fails at once with SQLITE_BUSY (Store::init in mailcore/src/store/mod.rs). Set a short busy_timeout in init.
Activity