Files
tutabridge/crates
Anthony 0ef2056235 Retry attachment loads asynchronously without blocking the prefetch loop
The single in-line retry budget (2/4/8/16s, ~30s total) bumps the
session-key-transient race down but does not solve it: self-sends can
take longer than 30s to surface a usable File entity. Worse, the
in-line wait blocks the whole prefetch sweep on the offending mail.

Replace the strategy with an async pending state:

* New `attachments_pending: bool` on `StoredMail`. Set when a
  prefetch_details pass sees `is_transient_attachment_error(e)`; the
  body-only RFC 2822 is still written to disk + the store so IMAP keeps
  serving the message immediately.
* Second pass in `prefetch_details` retries the attachment-only step
  for any mail flagged pending, throttled by a per-mail
  `HashMap<element_id, Instant>` (`ATTACHMENT_RETRY_THROTTLE = 60s`).
  On success the cached .eml is rewritten as multipart, the flag is
  cleared, and the throttle entry is forgotten. On permanent failure
  the flag is also cleared so we stop hammering the server.
* `prefetch_loop` now wakes either on a store mutation **or** after
  `ATTACHMENT_RETRY_THROTTLE` when any throttle entry exists, so the
  retry happens even if no other mail traffic touches the store.

Bridge-side adds `MailStore::update_mail_rfc2822` (rewrite the body
without touching cached details), and threads the new field through
every `StoredMail` construction (tests included). SDK-side bumps the
in-line `load_file_with_retry` budget to 2/4/8/16s so most propagation
delays still resolve before we surface the transient error to the
pending path.
2026-05-28 23:03:51 +02:00
..