Skip to content

Commit 1f3dde2

Browse files
add exponential backoff option to reconnect plugin (#15)
* feat(plugins/reconnect): add exponential backoff option * test(plugins/antiflood): reduce delay used in test * chore(deps): upgrade to [email protected]
1 parent 3c56dd7 commit 1f3dde2

File tree

6 files changed

+44
-13
lines changed

6 files changed

+44
-13
lines changed

API.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ const client = new Client({
335335

336336
Enables auto reconnect.
337337

338-
Takes boolean or `{ attempts?: number, delay?: number }`.
338+
Takes a boolean or `{ attempts?: number, delay?: number, exponentialBackoff?: boolean }`.
339339

340340
Default to `false` or `{ attempts: 10, delay: 5 }` if set to `true`.
341341

@@ -358,6 +358,18 @@ const client = new Client({
358358
});
359359
```
360360

361+
Tries to reconnect `5` times with an initial delay of `3` seconds with an exponential backoff:
362+
363+
```ts
364+
const client = new Client({
365+
reconnect: {
366+
attempts: 5,
367+
delay: 3,
368+
exponentialBackoff: true,
369+
},
370+
});
371+
```
372+
361373
### option: resolveInvalidNames
362374

363375
Auto resolve invalid names (for nick and username).

deps.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ export {
44
green,
55
red,
66
stripColor,
7-
} from "https://deno.land/std@0.203.0/fmt/colors.ts";
7+
} from "https://deno.land/std@0.224.0/fmt/colors.ts";
88

9-
export { assertArrayIncludes } from "https://deno.land/std@0.203.0/assert/assert_array_includes.ts";
10-
export { assertEquals } from "https://deno.land/std@0.203.0/assert/assert_equals.ts";
11-
export { assertExists } from "https://deno.land/std@0.203.0/assert/assert_exists.ts";
12-
export { assertMatch } from "https://deno.land/std@0.203.0/assert/assert_match.ts";
13-
export { assertRejects } from "https://deno.land/std@0.203.0/assert/assert_rejects.ts";
14-
export { assertThrows } from "https://deno.land/std@0.203.0/assert/assert_throws.ts";
9+
export { assertArrayIncludes } from "https://deno.land/std@0.224.0/assert/assert_array_includes.ts";
10+
export { assertEquals } from "https://deno.land/std@0.224.0/assert/assert_equals.ts";
11+
export { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts";
12+
export { assertMatch } from "https://deno.land/std@0.224.0/assert/assert_match.ts";
13+
export { assertRejects } from "https://deno.land/std@0.224.0/assert/assert_rejects.ts";
14+
export { assertThrows } from "https://deno.land/std@0.224.0/assert/assert_throws.ts";
1515

1616
export { Queue } from "https://deno.land/x/[email protected]/mod.ts";

plugins/antiflood_test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { mock } from "../testing/mock.ts";
44

55
describe("plugins/antiflood", (test) => {
66
test("send two PRIVMSG with delay", async () => {
7-
const { client, server } = await mock({ floodDelay: 250 });
7+
const { client, server } = await mock({ floodDelay: 10 });
88

99
client.privmsg("#channel", "Hello world");
1010
client.privmsg("#channel", "Hello world, again");
@@ -16,7 +16,7 @@ describe("plugins/antiflood", (test) => {
1616
]);
1717

1818
// Wait for second message to make it through
19-
await delay(1000);
19+
await delay(100);
2020
raw = server.receive();
2121

2222
// Second message now dispatched to server

plugins/reconnect.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface ReconnectFeatures {
66
options: {
77
/** Enables auto reconnect.
88
*
9-
* Takes `boolean` or `{ attempts?: number, delay?: number }`.
9+
* Takes a boolean or `{ attempts?: number, delay?: number, exponentialBackoff?: boolean }`.
1010
*
1111
* Default to `false` or `{ attempts: 10, delay: 5 }` if set to `true`. */
1212
reconnect?: boolean | {
@@ -19,16 +19,22 @@ interface ReconnectFeatures {
1919
*
2020
* Default to `5` seconds. */
2121
delay?: number;
22+
23+
/** Enables exponential backoff.
24+
*
25+
* Default to `false`. */
26+
exponentialBackoff?: boolean;
2227
};
2328
};
2429
events: {
25-
"reconnecting": RemoteAddr;
30+
reconnecting: RemoteAddr;
2631
};
2732
}
2833

2934
const DEFAULT_RECONNECT = false;
3035
const DEFAULT_ATTEMPTS = 10;
3136
const DEFAULT_DELAY = 5;
37+
const DEFAULT_BACKOFF_FACTOR = { STATIC: 1, EXPONENTIAL: 2 };
3238

3339
export default createPlugin(
3440
"reconnect",
@@ -44,11 +50,16 @@ export default createPlugin(
4450
const {
4551
attempts = DEFAULT_ATTEMPTS,
4652
delay = DEFAULT_DELAY,
53+
exponentialBackoff,
4754
} = config;
4855

4956
let currentAttempts = 0;
5057
let timeout: number | undefined;
5158

59+
const backoffFactor = exponentialBackoff
60+
? DEFAULT_BACKOFF_FACTOR.EXPONENTIAL
61+
: DEFAULT_BACKOFF_FACTOR.STATIC;
62+
5263
const delayReconnect = () => {
5364
clearTimeout(timeout);
5465
if (currentAttempts === attempts) return;
@@ -59,7 +70,7 @@ export default createPlugin(
5970
const { hostname, port, tls } = remoteAddr;
6071
timeout = setTimeout(
6172
async () => await client.connect(hostname, port, tls),
62-
delay * 1000,
73+
delay * 1000 * Math.pow(backoffFactor, currentAttempts - 1),
6374
);
6475
};
6576

plugins/reconnect_test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ describe("plugins/reconnect", (test) => {
1919
await client.once("reconnecting");
2020

2121
assertEquals(reconnecting, 1);
22+
23+
await client.once("error"); // wait for timeout clearing
2224
});
2325

2426
test("reconnect on server error", async () => {
@@ -36,6 +38,8 @@ describe("plugins/reconnect", (test) => {
3638
await client.once("reconnecting");
3739

3840
assertEquals(reconnecting, 1);
41+
42+
await client.once("connecting"); // wait for timeout clearing
3943
});
4044

4145
test("reset attemps when RPL_WELCOME is received", async () => {
@@ -67,6 +71,8 @@ describe("plugins/reconnect", (test) => {
6771
await client.once("reconnecting");
6872

6973
assertEquals(reconnecting, 3);
74+
75+
await client.once("connecting"); // wait for timeout clearing
7076
});
7177

7278
test("not reconnect if disabled", async () => {

testing/conn.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ export class MockConn extends EventEmitter<Events> implements Deno.Conn {
6161
ref(): void {}
6262

6363
unref(): void {}
64+
65+
[Symbol.dispose](): void {}
6466
}

0 commit comments

Comments
 (0)