fix(prekey): align bounded-retry ttl with outer UPLOAD_TIMEOUT race
Bug found while reviewing pre-key auto-replenishment behavior with the
user. uploadPreKeys is wrapped in:
Promise.race([uploadLogic(), 30s timeout]) ← UPLOAD_TIMEOUT
Inside uploadLogic, my previous commit configured bounded-retry with
ttlMs=60_000 (60s). Result: outer race always wins at 30s, bounded-retry
never reaches its natural give-up. We lose the structured logs / metrics
emitted on TTL exhaustion, AND if a retry was about to succeed at second
29, it gets killed by the outer race.
Fix:
- ttlMs reduced to UPLOAD_TIMEOUT - 2_000 = 28_000ms (safety margin so
bounded-retry always reaches give-up before the outer race).
- perAttemptTimeoutMs reduced 20s -> 8s so multiple attempts fit in 28s.
- delays trimmed to [1000, 2000, 4000, 8000] (4 attempts, ≈15s with
delays plus per-attempt time = comfortably within 28s budget).
- query(node) timeout aligned with PER_ATTEMPT_TIMEOUT_MS=8s.
Pre-key replenishment system (existed before this PR, untouched):
- MIN_PREKEY_COUNT=200 (replenishment threshold)
- INITIAL_PREKEY_COUNT=800 (top-up target — matches WA Business CDP
capture: prekey-store=812 on registration)
- Triggered on: CB:success login, every 6h auto-sync, Bad MAC recovery,
specific peer prekey miss.
Bounded-retry only handles HOW the upload retries on transient failure,
not WHEN. The two layers are orthogonal.
Build clean, 35/35 suites, 809/809 tests pass.
This commit is contained in:
+12
-4
@@ -645,7 +645,14 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
// Upload to server. Bounded-retry handles backoff (replaces both
|
||||
// the previous circuit breaker AND the manual exponential backoff
|
||||
// retry loop with maxRetries=3).
|
||||
const PER_ATTEMPT_TIMEOUT_MS = 20_000
|
||||
//
|
||||
// IMPORTANT: bounded-retry's ttlMs MUST be < UPLOAD_TIMEOUT (the
|
||||
// outer Promise.race below). Otherwise the outer race fires first
|
||||
// and bounded-retry never reaches its natural give-up — losing
|
||||
// structured logs / metrics. Use UPLOAD_TIMEOUT - 2s as a safety
|
||||
// margin so bounded-retry always wins.
|
||||
const PER_ATTEMPT_TIMEOUT_MS = 8_000
|
||||
const RETRY_TTL_MS = UPLOAD_TIMEOUT - 2_000
|
||||
// Pass the matching timeoutMs to query() so a stale attempt does
|
||||
// not keep an iq listener registered after bounded-retry has moved
|
||||
// on to the next attempt (Copilot review on PR #393).
|
||||
@@ -658,9 +665,10 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
try {
|
||||
await withBoundedRetry(uploadToServer, {
|
||||
name: 'uploadPreKeys',
|
||||
// 1s -> 2s -> 4s -> 8s -> 10s (cap matches old MAX backoff)
|
||||
delays: [1000, 2000, 4000, 8000, 10000],
|
||||
ttlMs: 60_000,
|
||||
// 1s -> 2s -> 4s -> 8s (cap). Max 4 attempts fit comfortably
|
||||
// within RETRY_TTL_MS (28s) given perAttemptTimeoutMs=8s.
|
||||
delays: [1000, 2000, 4000, 8000],
|
||||
ttlMs: RETRY_TTL_MS,
|
||||
perAttemptTimeoutMs: PER_ATTEMPT_TIMEOUT_MS,
|
||||
logger
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user