MessageWeave/cloudflare-worker/test
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
..
backends.test.js docs: add bilingual guides and callback setup in SPA 2026-10-01 02:36:03 +08:00
health.test.js feat(lb): /healthz 回显版本号 LB_VERSION,确认线上是哪次部署在回答 2026-09-30 20:21:48 +08:00
index.test.js feat(worker): redirect HTTP to HTTPS 2026-10-01 02:52:01 +08:00
lb.test.js fix: stop swallowing reconcile errors — surface reason in 503 body 2026-10-12 17:43:26 +08:00