Skip to content

Commit

Permalink
Add jitter support to BackOff class
Browse files Browse the repository at this point in the history
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
  • Loading branch information
automated-signal and indutny-signal committed Sep 28, 2021
1 parent 029cb74 commit f2b7bd9
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
28 changes: 28 additions & 0 deletions ts/test-both/util/BackOff_test.ts
Expand Up @@ -42,4 +42,32 @@ describe('BackOff', () => {
assert.strictEqual(b.getAndIncrement(), 1);
assert.strictEqual(b.getAndIncrement(), 2);
});

it('should apply jitter', () => {
const b = new BackOff([1, 2, 3], {
jitter: 1,
random: () => 0.5,
});

assert.strictEqual(b.getIndex(), 0);
assert.strictEqual(b.isFull(), false);

assert.strictEqual(b.get(), 1);
assert.strictEqual(b.getAndIncrement(), 1);
assert.strictEqual(b.get(), 2.5);
assert.strictEqual(b.getIndex(), 1);
assert.strictEqual(b.isFull(), false);

assert.strictEqual(b.getAndIncrement(), 2.5);
assert.strictEqual(b.getIndex(), 2);
assert.strictEqual(b.isFull(), true);

assert.strictEqual(b.getAndIncrement(), 3.5);
assert.strictEqual(b.getIndex(), 2);
assert.strictEqual(b.isFull(), true);

assert.strictEqual(b.getAndIncrement(), 3.5);
assert.strictEqual(b.getIndex(), 2);
assert.strictEqual(b.isFull(), true);
});
});
8 changes: 6 additions & 2 deletions ts/textsecure/SocketManager.ts
Expand Up @@ -35,6 +35,8 @@ const TEN_SECONDS = 10 * durations.SECOND;

const FIVE_MINUTES = 5 * durations.MINUTE;

const JITTER = 5 * durations.SECOND;

export type SocketManagerOptions = Readonly<{
url: string;
certificateAuthority: string;
Expand All @@ -57,7 +59,9 @@ export type SocketManagerOptions = Readonly<{
// Incoming requests on unauthenticated resource are not currently supported.
// WebSocketResource is responsible for their immediate termination.
export class SocketManager extends EventListener {
private backOff = new BackOff(FIBONACCI_TIMEOUTS);
private backOff = new BackOff(FIBONACCI_TIMEOUTS, {
jitter: JITTER,
});

private authenticated?: AbortableProcess<WebSocketResource>;

Expand Down Expand Up @@ -202,7 +206,7 @@ export class SocketManager extends EventListener {
return;
}

if (code !== 500 && code !== -1) {
if (!(code >= 500 && code <= 599) && code !== -1) {
// No reconnect attempt should be made
return;
}
Expand Down
24 changes: 22 additions & 2 deletions ts/util/BackOff.ts
Expand Up @@ -15,13 +15,33 @@ export const FIBONACCI_TIMEOUTS: ReadonlyArray<number> = [
55 * SECOND,
];

export type BackOffOptionsType = Readonly<{
jitter?: number;

// Testing
random?: () => number;
}>;

const DEFAULT_RANDOM = () => Math.random();

export class BackOff {
private count = 0;

constructor(private readonly timeouts: ReadonlyArray<number>) {}
constructor(
private readonly timeouts: ReadonlyArray<number>,
private readonly options: BackOffOptionsType = {}
) {}

public get(): number {
return this.timeouts[this.count];
let result = this.timeouts[this.count];
const { jitter = 0, random = DEFAULT_RANDOM } = this.options;

// Do not apply jitter larger than the timeout value. It is supposed to be
// activated for longer timeouts.
if (jitter < result) {
result += random() * jitter;
}
return result;
}

public getAndIncrement(): number {
Expand Down

0 comments on commit f2b7bd9

Please sign in to comment.