@@ -106,6 +106,7 @@ class Redis extends Commander implements DataHandledable {
106
106
private connectionEpoch = 0 ;
107
107
private retryAttempts = 0 ;
108
108
private manuallyClosing = false ;
109
+ private socketTimeoutTimer : NodeJS . Timeout | undefined ;
109
110
110
111
// Prepare autopipelines structures
111
112
private _autoPipelines = new Map ( ) ;
@@ -523,6 +524,10 @@ class Redis extends Commander implements DataHandledable {
523
524
if ( Command . checkFlag ( "WILL_DISCONNECT" , command . name ) ) {
524
525
this . manuallyClosing = true ;
525
526
}
527
+
528
+ if ( this . options . socketTimeout !== undefined && this . socketTimeoutTimer === undefined ) {
529
+ this . setSocketTimeout ( ) ;
530
+ }
526
531
}
527
532
528
533
if ( command . name === "select" && isInt ( command . args [ 0 ] ) ) {
@@ -537,6 +542,23 @@ class Redis extends Commander implements DataHandledable {
537
542
return command . promise ;
538
543
}
539
544
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
+ console . log ( 'GOT DATA, CLEARING TIMER' ) ;
555
+ clearTimeout ( this . socketTimeoutTimer ) ;
556
+ this . socketTimeoutTimer = undefined ;
557
+ if ( this . commandQueue . length === 0 ) return ;
558
+ this . setSocketTimeout ( ) ;
559
+ } ) ;
560
+ }
561
+
540
562
scanStream ( options ?: ScanStreamOptions ) {
541
563
return this . createScanStream ( "scan" , { options } ) ;
542
564
}
0 commit comments