@@ -107,13 +107,27 @@ class Cluster extends EventEmitter {
107107 this . offlineQueue = new Deque ( )
108108 }
109109
110+ clearNodesRefreshInterval ( ) {
111+ if ( this . slotsTimer ) {
112+ clearTimeout ( this . slotsTimer )
113+ this . slotsTimer = null
114+ }
115+ }
116+
110117 resetNodesRefreshInterval ( ) {
111118 if ( this . slotsTimer ) {
112119 return
113120 }
114- this . slotsTimer = setInterval ( function ( ) {
115- this . refreshSlotsCache ( )
116- } . bind ( this ) , this . options . slotsRefreshInterval )
121+ const nextRound = ( ) => {
122+ this . slotsTimer = setTimeout ( ( ) => {
123+ debug ( 'refreshing slot caches... (triggered by "slotsRefreshInterval" option)' )
124+ this . refreshSlotsCache ( ( ) => {
125+ nextRound ( )
126+ } )
127+ } , this . options . slotsRefreshInterval )
128+ }
129+
130+ nextRound ( )
117131 }
118132
119133 /**
@@ -245,10 +259,7 @@ class Cluster extends EventEmitter {
245259 this . reconnectTimeout = null
246260 debug ( 'Canceled reconnecting attempts' )
247261 }
248- if ( this . slotsTimer ) {
249- clearInterval ( this . slotsTimer )
250- this . slotsTimer = null
251- }
262+ this . clearNodesRefreshInterval ( )
252263
253264 this . subscriber . stop ( )
254265 if ( status === 'wait' ) {
@@ -276,10 +287,7 @@ class Cluster extends EventEmitter {
276287 clearTimeout ( this . reconnectTimeout )
277288 this . reconnectTimeout = null
278289 }
279- if ( this . slotsTimer ) {
280- clearInterval ( this . slotsTimer )
281- this . slotsTimer = null
282- }
290+ this . clearNodesRefreshInterval ( )
283291
284292 this . subscriber . stop ( )
285293
@@ -471,6 +479,7 @@ class Cluster extends EventEmitter {
471479 }
472480 _this . connectionPool . findOrCreate ( _this . natMapper ( key ) )
473481 tryConnection ( )
482+ debug ( 'refreshing slot caches... (triggered by MOVED error)' )
474483 _this . refreshSlotsCache ( )
475484 } ,
476485 ask : function ( slot , key ) {
@@ -608,9 +617,19 @@ class Cluster extends EventEmitter {
608617 if ( ! redis ) {
609618 return callback ( new Error ( 'Node is disconnected' ) )
610619 }
611- redis . cluster ( 'slots' , timeout ( ( err , result ) => {
620+
621+ // Use a duplication of the connection to avoid
622+ // timeouts when the connection is in the blocking
623+ // mode (e.g. waiting for BLPOP).
624+ const duplicatedConnection = redis . duplicate ( {
625+ enableOfflineQueue : true ,
626+ enableReadyCheck : false ,
627+ retryStrategy : null ,
628+ connectionName : 'ioredisClusterRefresher'
629+ } )
630+ duplicatedConnection . cluster ( 'slots' , timeout ( ( err , result ) => {
631+ duplicatedConnection . disconnect ( )
612632 if ( err ) {
613- redis . disconnect ( )
614633 return callback ( err )
615634 }
616635 if ( this . status === 'disconnecting' || this . status === 'close' || this . status === 'end' ) {
0 commit comments