From d5796b36b6a74c5fa7e1ad58e689006b2f2f2557 Mon Sep 17 00:00:00 2001 From: Renato Alcara Date: Mon, 27 Apr 2026 00:42:09 -0300 Subject: [PATCH] docs(retry): clarify abort semantics + remove stale circuit-breaker mention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two doc-only fixes from PR #393 review (Copilot): 1. **bounded-retry.ts BoundedRetryOptions.signal** The previous one-line "if aborted, give up immediately" was technically correct from the loop's perspective but misleading about what happens to an in-flight operation. Expanded to describe the three observation points: sleep wakes immediately, in-flight attempt is forwarded the per-attempt signal (only truly immediate if the operation itself observes it), and the next loop iteration throws BoundedRetryAbortedError. 2. **retry-utils.ts module-level JSDoc** The header still listed "Circuit breaker integration" as a feature. The circuitBreaker option was removed in commit b531b46999 and the withRetry/retryable/RetryManager helpers in 0f2402da58. Updated the header to describe the actual current surface (used for Bad MAC recovery on decrypt path) and recommend withBoundedRetry for socket operations. Build clean, 35/35 suites, 809/809 tests pass. Note: not addressing the suppressed comment about removed APIs being a breaking change — per maintainer policy this fork has a single consumer, downstream forks absorb on merge. --- src/Utils/bounded-retry.ts | 13 ++++++++++++- src/Utils/retry-utils.ts | 14 +++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Utils/bounded-retry.ts b/src/Utils/bounded-retry.ts index 0cd67779..fdc376ca 100644 --- a/src/Utils/bounded-retry.ts +++ b/src/Utils/bounded-retry.ts @@ -129,7 +129,18 @@ export interface BoundedRetryOptions { shouldRetry?: (err: Error, attempt: number) => boolean /** Hook fired before each retry */ onRetry?: (err: Error, attempt: number, delayMs: number) => void - /** AbortSignal — if aborted, give up immediately */ + /** + * AbortSignal — when fired, the loop stops at the next observation point: + * - If the loop is sleeping between retries, the sleep rejects immediately. + * - If an attempt is in flight, the abort is forwarded to the operation + * via the per-attempt signal. The operation must ITSELF observe the + * signal (e.g. `(signal) => fetch({ signal })`) for cancellation to + * be truly immediate; otherwise it cancels at the next per-attempt + * timeout boundary. + * - Either way, on the next loop iteration BoundedRetryAbortedError is + * thrown, so the caller never sees more than one trailing attempt + * after the abort. + */ signal?: AbortSignal /** Optional logger for structured retry/give-up/recovery logs */ logger?: ILogger diff --git a/src/Utils/retry-utils.ts b/src/Utils/retry-utils.ts index cce180d0..2907ea19 100644 --- a/src/Utils/retry-utils.ts +++ b/src/Utils/retry-utils.ts @@ -6,9 +6,17 @@ * - Jitter to avoid thundering herd * - Configurable max attempts * - Customizable retry predicates - * - Circuit breaker integration - * - Event hooks - * - Cancellation support + * - Cancellation support (AbortSignal) + * + * Used by `decode-wa-message.ts` for Bad MAC retry recovery on the decrypt + * path. For socket-operation retries (uploadPreKeys etc.) prefer + * `withBoundedRetry` from `./bounded-retry.ts`, which is empirically + * aligned with WhatsApp Android's per-operation backoff. + * + * NOTE: the previous `circuitBreaker` integration option, the `withRetry` + * decorator, the `retryable` wrapper and the `RetryManager` class were + * removed when the socket-level circuit breaker was retired — see PR #393 + * for the rationale. * * @module Utils/retry-utils */