Skip to content

Commit 687cd15

Browse files
authored
feat: Add interval option for connections (denodrivers#399)
1 parent eb5857e commit 687cd15

File tree

3 files changed

+58
-5
lines changed

3 files changed

+58
-5
lines changed

connection/connection.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@
2626
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2727
*/
2828

29-
import { bold, BufReader, BufWriter, joinPath, yellow } from "../deps.ts";
29+
import {
30+
bold,
31+
BufReader,
32+
BufWriter,
33+
delay,
34+
joinPath,
35+
yellow,
36+
} from "../deps.ts";
3037
import { DeferredStack } from "../utils/deferred.ts";
3138
import { getSocketName, readUInt32BE } from "../utils/utils.ts";
3239
import { PacketWriter } from "./packet.ts";
@@ -461,10 +468,23 @@ export class Connection {
461468
error = e;
462469
}
463470
} else {
464-
// If the reconnection attempts are set to zero the client won't attempt to
465-
// reconnect, but it won't error either, this "no reconnections" behavior
466-
// should be handled wherever the reconnection is requested
471+
let interval =
472+
typeof this.#connection_params.connection.interval === "number"
473+
? this.#connection_params.connection.interval
474+
: 0;
467475
while (reconnection_attempts < max_reconnections) {
476+
// Don't wait for the interval on the first connection
477+
if (reconnection_attempts > 0) {
478+
if (
479+
typeof this.#connection_params.connection.interval === "function"
480+
) {
481+
interval = this.#connection_params.connection.interval(interval);
482+
}
483+
484+
if (interval > 0) {
485+
await delay(interval);
486+
}
487+
}
468488
try {
469489
await this.#startup();
470490
break;

connection/connection_params.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ export interface ConnectionOptions {
4848
* default: `1`
4949
*/
5050
attempts: number;
51+
/**
52+
* The time to wait before attempting each reconnection (in milliseconds)
53+
*
54+
* You can provide a fixed number or a function to call each time the
55+
* connection is attempted. By default, the interval will be a function
56+
* with an exponential backoff increasing by 500 milliseconds
57+
*/
58+
interval: number | ((previous_interval: number) => number);
5159
}
5260

5361
/** https://www.postgresql.org/docs/14/libpq-ssl.html#LIBPQ-SSL-PROTECTION */
@@ -299,6 +307,7 @@ const DEFAULT_OPTIONS:
299307
applicationName: "deno_postgres",
300308
connection: {
301309
attempts: 1,
310+
interval: (previous_interval) => previous_interval + 500,
302311
},
303312
host: "127.0.0.1",
304313
socket: "/tmp",
@@ -425,6 +434,8 @@ export function createParams(
425434
connection: {
426435
attempts: params?.connection?.attempts ??
427436
DEFAULT_OPTIONS.connection.attempts,
437+
interval: params?.connection?.interval ??
438+
DEFAULT_OPTIONS.connection.interval,
428439
},
429440
database: params.database ?? pgEnv.database,
430441
hostname: host,

docs/README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ the database name and your user, the rest of them have sensible defaults to save
7878
up time when configuring your connection, such as the following:
7979

8080
- connection.attempts: "1"
81+
- connection.interval: Exponential backoff increasing the time by 500 ms on
82+
every reconnection
8183
- hostname: If host_type is set to TCP, it will be "127.0.0.1". Otherwise, it
8284
will default to the "/tmp" folder to look for a socket connection
8385
- host_type: "socket", unless a host is manually specified
@@ -195,12 +197,32 @@ try {
195197
}
196198
```
197199

198-
Your initial connection will also be affected by this setting, in a slightly
200+
Your initial connection will also be affected by this setting in a slightly
199201
different manner than already active errored connections. If you fail to connect
200202
to your database in the first attempt, the client will keep trying to connect as
201203
many times as requested, meaning that if your attempt configuration is three,
202204
your total first-connection-attempts will ammount to four.
203205

206+
Additionally you can set an interval before each reconnection by using the
207+
`interval` parameter. This can be either a plane number or a function where the
208+
developer receives the previous interval and returns the new one, making it easy
209+
to implement exponential backoff (Note: the initial interval for this function
210+
is always gonna be zero)
211+
212+
```ts
213+
// Eg: A client that increases the reconnection time by multiplying the previous interval by 2
214+
const client = new Client({
215+
connection: {
216+
attempts: 0,
217+
interval: (prev_interval) => {
218+
// Initial interval is always gonna be zero
219+
if (prev_interval === 0) return 2;
220+
return prev_interval * 2;
221+
},
222+
},
223+
});
224+
```
225+
204226
### Unix socket connection
205227

206228
On Unix systems, it's possible to connect to your database through IPC sockets

0 commit comments

Comments
 (0)