Files
buzz/desktop/src-tauri
Taylor HoandMongo f0c71437ea fix(link-preview): stop a transient fetch failure from blanking a valid card
A valid link (e.g. a GitHub PR page) could render no preview card for five
minutes after a single unlucky fetch, then quietly work again. One slow
handshake, a rate-limit blip, or a 5xx would poison the card.

Two paths funneled a transient failure into the same sticky negative cache as
a genuine "no metadata" miss:
- The resolver's fetch loader caught any rejection (timeout, network error) as
  a plain null and cached it under NULL_METADATA_RETRY_MS (5 minutes).
- The native fetcher returned Ok(None) for a retryable page status (429, 408,
  425, 5xx), which the resolver also cached for the full miss TTL.

Distinguish transient failures from hard misses:
- The loader now records a rejected fetch as transient and caches it for the
  short transient TTL (30s) instead of the 5-minute miss TTL. A resolved null
  (200 + HTML + no metadata) still holds the full miss TTL.
- The native fetcher surfaces a retryable page status as an error (via a shared
  is_transient_status helper, reused by the image path) so it takes the short
  transient TTL rather than the sticky negative cache.

Also widen the per-request timeout from 4s to 6s (total 10s to 15s) so slow
networks stop tripping the transient path in the first place.

Tests: JS regression that a rejected fetch clears well before the 5-minute
miss TTL while a genuine null miss stays cached; the rejected-retry test now
asserts the 30s transient boundary; Rust unit test that retryable statuses are
transient and permanent ones (404/403/401/410) are hard misses. Full desktop
unit suite 4580 passed; link_preview Rust suite 22 passed.

Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
2026-08-10 15:01:57 -07:00
..