Skip to content

Commit 95f3d18

Browse files
authored
Make backoff account for already-elapsed time. (#1132)
1 parent 7ef7d51 commit 95f3d18

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

packages/firestore/src/remote/backoff.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ const LOG_TAG = 'ExponentialBackoff';
3131
export class ExponentialBackoff {
3232
private currentBaseMs: number;
3333
private timerPromise: CancelablePromise<void> | null = null;
34+
/** The last backoff attempt, as epoch milliseconds. */
35+
private lastAttemptTime = Date.now();
3436

3537
constructor(
3638
/**
@@ -92,18 +94,36 @@ export class ExponentialBackoff {
9294

9395
// First schedule using the current base (which may be 0 and should be
9496
// honored as such).
95-
const delayWithJitterMs = this.currentBaseMs + this.jitterDelayMs();
97+
const desiredDelayWithJitterMs = Math.floor(
98+
this.currentBaseMs + this.jitterDelayMs()
99+
);
100+
101+
// Guard against lastAttemptTime being in the future due to a clock change.
102+
const delaySoFarMs = Math.max(0, Date.now() - this.lastAttemptTime);
103+
104+
// Guard against the backoff delay already being past.
105+
const remainingDelayMs = Math.max(
106+
0,
107+
desiredDelayWithJitterMs - delaySoFarMs
108+
);
109+
96110
if (this.currentBaseMs > 0) {
97111
log.debug(
98112
LOG_TAG,
99-
`Backing off for ${delayWithJitterMs} ms ` +
100-
`(base delay: ${this.currentBaseMs} ms)`
113+
`Backing off for ${remainingDelayMs} ms ` +
114+
`(base delay: ${this.currentBaseMs} ms, ` +
115+
`delay with jitter: ${desiredDelayWithJitterMs} ms, ` +
116+
`last attempt: ${delaySoFarMs} ms ago)`
101117
);
102118
}
119+
103120
this.timerPromise = this.queue.enqueueAfterDelay(
104121
this.timerId,
105-
delayWithJitterMs,
106-
op
122+
remainingDelayMs,
123+
() => {
124+
this.lastAttemptTime = Date.now();
125+
return op();
126+
}
107127
);
108128

109129
// Apply backoff factor to determine next delay and ensure it is within

0 commit comments

Comments
 (0)