Commit Graph

3 Commits

Author SHA1 Message Date
anonsaber 298d487782 fix: stop swallowing reconcile errors — surface reason in 503 body
Two layers were masking the real cause of reconcile failures:

1. Backend: worker.rs reconciled all JMAP/Redis failures into Err(()),
   so handle_reconcile returned 503 with {"error":"reconcile_retry"} but
   no indication of WHICH step broke. Now reconcile() returns
   Result<String, &'static str> with diagnostic codes:
   - jmap_session_failed — session_state() failed (JMAP unreachable/auth)
   - jmap_list_failed — list_emails_page() failed
   - reconcile_budget_exhausted — budget/pages exhausted before any progress
   - reconcile_no_progress — walk made no progress
   - reconcile_lease_lost — background heartbeat lost the lock
   - reconcile_state_write_failed — set_reconcile_state() Redis failure
   - enqueue_failed — claim_dedup_and_enqueue() Redis failure

   The 503 body now includes a "reason" field alongside the documented
   "reconcile_retry" error code, so operators can see the cause without
   server-side logs. The error code is unchanged (stable contract for
   cron-drain.sh and other callers).

2. Cloudflare Worker LB: forwardWithFailover treated all 5xx as backend
   failure and replaced the real response body with synthesized
   "all backends failed: ..." text. Now the last 5xx HTTP response is
   kept and passed through, so the backend's real error body (including
   the new reason field) reaches the client. Pure network errors (no HTTP
   response at all) still get the synthesized 503 fallback.
2026-10-12 17:43:26 +08:00
anonsaber 656034d71d fix(lb): 可观测头写入不可变响应头不再把健康的 200 变成 503
mark() 往代理响应上写 `x-lb-backend`,但跨域且无 CORS 允许头的响应其
headers guard 是 immutable,`set` 抛 `TypeError: Can't modify immutable
headers.`;异常冒泡到 forwardWithFailover 的 catch 后被判成后端故障
(`backend ... unavailable (TypeError)`),重试耗尽返回 503。

后端一直健康:GET / 实际返回 200。/healthz 走 healthResponse() 自建
响应、不调 mark(),所以不受影响——这也正是它掩盖问题多年的原因。

mark() 现在在响应头不可变时静默放弃观测头,绝不阻塞响应返回;补两条
回归测试(2xx 不可变响应必须原样返回且不触发故障转移;5xx 不可变响应
仍正常故障转移)。

验证:wrangler dev --local 下 / /healthz /ready /api/status /assets/*
全部 200(修复前 / 与 /api/status 为 503);node --test 34/34 通过。
2026-09-30 20:02:18 +08:00
anonsaber 4f5eb9293d chore(worker): rename proxy to lb and ignore build cache
- cloudflare-worker: unify terminology proxy -> lb/forward
  (PROXIED_ROUTES -> LB_ROUTES, proxyWithFailover -> forwardWithFailover,
  proxy.js -> lb.js, related tests and README); renames/wording only, no behavior change
- Dockerfile: crates.io index mirror rsproxy.cn -> mirrors.ustc.edu.cn
- .gitignore: ignore build verification cache .gate-cache/ (cargo registry + rustup, ~1.5G)
2026-09-27 12:52:55 +08:00