mt: clamp reconnect delay to cap after jitter
reconnectDelayMs capped base at MAX_RECONNECT_DELAY_MS before adding
+/-20% jitter, so a capped attempt could return ~72s, above the
documented 60s cap. Clamp the post-jitter result. Deepaudit 07-20 MINOR.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2 files changed,
+12 insertions,
-2 deletions
| 40 |
40 |
|
}
|
| 41 |
41 |
|
});
|
| 42 |
42 |
|
|
|
43 |
+ |
test("jitter never pushes the delay past the documented cap", () => {
|
|
44 |
+ |
// +20% on a capped base is ~72s; the result must still honor MAX_RECONNECT_DELAY_MS.
|
|
45 |
+ |
for (const attempt of [6, 10, 20, 1e6]) {
|
|
46 |
+ |
assert.equal(reconnectDelayMs(attempt, () => 0.999), MAX_RECONNECT_DELAY_MS);
|
|
47 |
+ |
}
|
|
48 |
+ |
});
|
|
49 |
+ |
|
| 43 |
50 |
|
test("jitter actually spreads clients out", () => {
|
| 44 |
51 |
|
// The point of jitter is that a fleet reconnecting after one deploy does not
|
| 45 |
52 |
|
// arrive in lockstep. Identical delays would defeat it.
|
| 49 |
49 |
|
const exponent = Math.min(Math.max(attempt, 0), MAX_EXPONENT);
|
| 50 |
50 |
|
const base = Math.min(1000 * 2 ** exponent, MAX_RECONNECT_DELAY_MS);
|
| 51 |
51 |
|
const span = base * JITTER_FRACTION;
|
| 52 |
|
- |
// Uniform across [base - span, base + span].
|
|
52 |
+ |
// Uniform across [base - span, base + span]. Jitter is added after the cap, so
|
|
53 |
+ |
// clamp the result back down: +20% on a capped base would otherwise return ~72s,
|
|
54 |
+ |
// above the documented MAX_RECONNECT_DELAY_MS.
|
| 53 |
55 |
|
const delta = random() * 2 * span - span;
|
| 54 |
|
- |
return Math.max(0, Math.round(base + delta));
|
|
56 |
+ |
const jittered = Math.round(base + delta);
|
|
57 |
+ |
return Math.min(MAX_RECONNECT_DELAY_MS, Math.max(0, jittered));
|
| 55 |
58 |
|
}
|
| 56 |
59 |
|
|
| 57 |
60 |
|
/** What the caller should do next. */
|