Skip to content

Commit 9f0a619

Browse files
committed
Add calculateRetryDelayFactor helper function
This is used to calculate the exponentially increasing delay. The function is used to calculate the reconnection delay - but does not keep track of the current reconnection attempt. Keeping track of the current reconnection attempt is reserved for the next few commits.
1 parent 4aaf219 commit 9f0a619

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

__tests__/index/retryConnectionDelay.test.ts

+29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// File Dependencies
22
import Sarus from "../../src/index";
33
import { WS } from "jest-websocket-mock";
4+
import { calculateRetryDelayFactor } from "../../src/index";
5+
import type { ExponentialBackoffParams } from "../../src/index";
46

57
const url = "ws://localhost:1234";
68

@@ -61,3 +63,30 @@ describe("retry connection delay", () => {
6163
});
6264
});
6365
});
66+
67+
describe("Exponential backoff delay", () => {
68+
it("will never be more than 8000 ms with rate set to 2", () => {
69+
// The initial delay shall be 1 s
70+
const initialDelay = 1000;
71+
const exponentialBackoffParams: ExponentialBackoffParams = {
72+
backoffRate: 2,
73+
// We put the ceiling at exactly 8000 ms
74+
backoffLimit: 8000,
75+
};
76+
expect(
77+
calculateRetryDelayFactor(exponentialBackoffParams, initialDelay, 0),
78+
).toBe(1000);
79+
expect(
80+
calculateRetryDelayFactor(exponentialBackoffParams, initialDelay, 1),
81+
).toBe(2000);
82+
expect(
83+
calculateRetryDelayFactor(exponentialBackoffParams, initialDelay, 2),
84+
).toBe(4000);
85+
expect(
86+
calculateRetryDelayFactor(exponentialBackoffParams, initialDelay, 3),
87+
).toBe(8000);
88+
expect(
89+
calculateRetryDelayFactor(exponentialBackoffParams, initialDelay, 4),
90+
).toBe(8000);
91+
});
92+
});

src/index.ts

+34-3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,29 @@ export interface ExponentialBackoffParams {
7878
backoffLimit: number;
7979
}
8080

81+
/*
82+
* Calculate the exponential backoff delay for a given number of connection
83+
* attempts.
84+
* @param {ExponentialBackoffParams} params - configuration parameters for
85+
* exponential backoff.
86+
* @param {number} initialDelay - the initial delay before any backoff is
87+
* applied
88+
* @param {number} connectionAttempts - the number of connection attempts
89+
* that have previously failed, excluding the original connection attempt that
90+
* succeeded
91+
* @returns {void} - set does not return
92+
*/
93+
export function calculateRetryDelayFactor(
94+
params: ExponentialBackoffParams,
95+
initialDelay: number,
96+
connectionAttempts: number,
97+
): number {
98+
return Math.min(
99+
initialDelay * Math.pow(params.backoffRate, connectionAttempts),
100+
params.backoffLimit,
101+
);
102+
}
103+
81104
export interface SarusClassParams {
82105
url: string;
83106
binaryType?: BinaryType;
@@ -363,12 +386,20 @@ export default class Sarus {
363386
}
364387

365388
/**
366-
* Reconnects the WebSocket client based on the retryConnectionDelay setting.
389+
* Reconnects the WebSocket client based on the retryConnectionDelay and
390+
* ExponentialBackoffParam setting.
367391
*/
368392
reconnect() {
369393
const self = this;
370-
const { retryConnectionDelay } = self;
371-
setTimeout(self.connect, retryConnectionDelay);
394+
const { retryConnectionDelay, exponentialBackoff } = self;
395+
396+
// If no exponential backoff is enabled, retryConnectionDelay will
397+
// be scaled by a factor of 1 and it will stay the original value.
398+
const delay = exponentialBackoff
399+
? calculateRetryDelayFactor(exponentialBackoff, retryConnectionDelay, 0)
400+
: retryConnectionDelay;
401+
402+
setTimeout(self.connect, delay);
372403
}
373404

374405
/**

0 commit comments

Comments
 (0)