Codex P2 review caught: `retry()` in retry-utils.ts iterates with
`for (let attempt = 1; ...)`, so the `attempt` passed to `shouldRetry` on
the first failure is 1, not 0. The previous `attempt < 1` was therefore
always false → no retry on unknown errors, contradicting the inline policy
comment ("one retry in case it was a transient blip").
Use `attempt < 2` so the SECOND pass happens (initial + 1 retry = 2 total
attempts, which matches `maxAttempts: 2`) and the third pass is refused.
The session-record / corrupted-session branches above already return false
unconditionally and are not affected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PRODUCTION BUG (still present after PR #396): inbound messages from the
smartphone take ~60s to surface in the consumer (zpro). PR #396 fixed the
PN/LID lock-vs-storage drift but did NOT clear the latency. Diff against the
known-good Pedro snapshot pinpointed the residual cause: this retry wrapper.
ROOT CAUSE:
`DECRYPTION_RETRY_OPTIONS.shouldRetry` retries 3× with exponential backoff
(200 ms → 400 ms → 800 ms ≈ 1.4 s per failed message) on
`'No matching sessions found'` and friends. After WhatsApp's LID/DSM rollout
own DSM messages flood in for sessions stored under the legacy `_1.0` format
that no longer matches the LID-addressed envelope, so EVERY DSM hits this
path. At ~30 DSM/min the accumulated backoff is ~42 s — enough to block
real-contact messages from reaching the buffer flush.
The Pedro snapshot (Feb 6 2026, 484 commits behind, confirmed fast in prod
on the same auth state) has NO retry wrapper at all: try once → fail → send
retry receipt → phone re-sends as `pkmsg` → fresh session → next message
decrypts cleanly. Total recovery ~300 ms, no pipeline backpressure.
WHY THE RETRIES WERE USELESS:
1. libsignal already scanned every stored session for the JID before throwing
`No matching sessions found`. Re-running the same lookup 200 ms later
gives the same answer — no new session record materialises in that window.
2. Bad MAC / counter errors mean the keys are simply wrong; retry doesn't
regenerate keys. (This branch was already correctly returning false.)
THIS PATCH:
- `sessionRecordErrors` now also returns `false` from `shouldRetry` (matches
the existing `corruptedSessionErrors` policy).
- Unknown errors retry exactly once (was twice) — quick blip recovery only.
- `maxAttempts` lowered to 2 to match.
- Big block comment captures the rationale so the next person doesn't add
retries back hoping it'll help.
Recovery still happens — just upstream, via the retry-receipt → pkmsg flow,
which is what WhatsApp protocol intends and what Pedro's working snapshot
relies on.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 10:30:22 -03:00
3 changed files with 42 additions and 14 deletions
returnattempt<2// Retry up to 2 times for unknown errors
// Unknown errors: one retry in case it was a transient blip.
// `attempt` is 1-based (retry-utils starts the loop at 1), so `attempt < 2`
// allows the second pass and returns false on the third.
returnattempt<2
}
}
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.