Skip to content

Commit c1a245b

Browse files
pinkieskyleibale
andauthored
Fork: feat: Socket timeout (#14)
* feat: add support for `socketTimeout` in `Redis` (#1882) Signed-off-by: Aleksandr Zinin <[email protected]> * fix: remove console.log Signed-off-by: Aleksandr Zinin <[email protected]> --------- Signed-off-by: Aleksandr Zinin <[email protected]> Co-authored-by: Leibale Eidelman <[email protected]>
1 parent 9505d6b commit c1a245b

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

lib/Redis.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class Redis extends Commander implements DataHandledable {
106106
private connectionEpoch = 0;
107107
private retryAttempts = 0;
108108
private manuallyClosing = false;
109+
private socketTimeoutTimer: NodeJS.Timeout | undefined;
109110

110111
// Prepare autopipelines structures
111112
private _autoPipelines = new Map();
@@ -523,6 +524,10 @@ class Redis extends Commander implements DataHandledable {
523524
if (Command.checkFlag("WILL_DISCONNECT", command.name)) {
524525
this.manuallyClosing = true;
525526
}
527+
528+
if (this.options.socketTimeout !== undefined && this.socketTimeoutTimer === undefined) {
529+
this.setSocketTimeout();
530+
}
526531
}
527532

528533
if (command.name === "select" && isInt(command.args[0])) {
@@ -537,6 +542,22 @@ class Redis extends Commander implements DataHandledable {
537542
return command.promise;
538543
}
539544

545+
private setSocketTimeout() {
546+
this.socketTimeoutTimer = setTimeout(() => {
547+
this.stream.destroy(new Error(`Socket timeout. Expecting data, but didn't receive any in ${this.options.socketTimeout}ms.`));
548+
this.socketTimeoutTimer = undefined;
549+
}, this.options.socketTimeout);
550+
551+
// this handler must run after the "data" handler in "DataHandler"
552+
// so that `this.commandQueue.length` will be updated
553+
this.stream.once("data", () => {
554+
clearTimeout(this.socketTimeoutTimer);
555+
this.socketTimeoutTimer = undefined;
556+
if (this.commandQueue.length === 0) return;
557+
this.setSocketTimeout();
558+
});
559+
}
560+
540561
scanStream(options?: ScanStreamOptions) {
541562
return this.createScanStream("scan", { options });
542563
}

lib/redis/RedisOptions.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ export interface CommonRedisOptions extends CommanderOptions {
1414
* a "Command timed out" error will be thrown.
1515
*/
1616
commandTimeout?: number;
17+
18+
/**
19+
* If the socket does not receive data within a set number of milliseconds:
20+
* 1. the socket is considered "dead" and will be destroyed
21+
* 2. the client will reject any running commands (altought they might have been processed by the server)
22+
* 3. the reconnect strategy will kick in (depending on the configuration)
23+
*/
24+
socketTimeout?: number;
25+
1726
/**
1827
* Enable/disable keep-alive functionality.
1928
* @link https://nodejs.org/api/net.html#socketsetkeepaliveenable-initialdelay

0 commit comments

Comments
 (0)