@@ -97,6 +97,7 @@ function RedisClient (options) {
97
97
this . auth_pass = options . auth_pass ;
98
98
this . selected_db = null ; // Save the selected db here, used when reconnecting
99
99
this . old_state = null ;
100
+ this . send_anyway = false ;
100
101
this . pipeline = 0 ;
101
102
this . options = options ;
102
103
// Init parser
@@ -172,6 +173,15 @@ RedisClient.prototype.create_stream = function () {
172
173
this . stream . on ( 'drain' , function ( ) {
173
174
self . drain ( ) ;
174
175
} ) ;
176
+
177
+ if ( this . options . socket_nodelay ) {
178
+ this . stream . setNoDelay ( ) ;
179
+ }
180
+
181
+ // Fire the command before redis is connected to be sure it's the first fired command
182
+ if ( typeof this . auth_pass === 'string' ) {
183
+ this . do_auth ( ) ;
184
+ }
175
185
} ;
176
186
177
187
RedisClient . prototype . handle_reply = function ( reply , command ) {
@@ -248,89 +258,51 @@ RedisClient.prototype.on_error = function (err) {
248
258
} ;
249
259
250
260
var noPasswordIsSet = / n o p a s s w o r d i s s e t / ;
251
- var loading = / L O A D I N G / ;
252
261
253
262
RedisClient . prototype . do_auth = function ( ) {
254
263
var self = this ;
255
-
256
264
debug ( 'Sending auth to ' + self . address + ' id ' + self . connection_id ) ;
257
265
258
- self . send_anyway = true ;
259
- self . send_command ( 'auth' , [ this . auth_pass ] , function ( err , res ) {
266
+ this . send_anyway = true ;
267
+ this . send_command ( 'auth' , [ this . auth_pass ] , function ( err , res ) {
260
268
if ( err ) {
261
- /* istanbul ignore if: this is almost impossible to test */
262
- if ( loading . test ( err . message ) ) {
263
- // If redis is still loading the db, it will not authenticate and everything else will fail
264
- debug ( 'Redis still loading, trying to authenticate later' ) ;
265
- setTimeout ( function ( ) {
266
- self . do_auth ( ) ;
267
- } , 333 ) ;
268
- return ;
269
- } else if ( noPasswordIsSet . test ( err . message ) ) {
269
+ if ( noPasswordIsSet . test ( err . message ) ) {
270
270
debug ( 'Warning: Redis server does not require a password, but a password was supplied.' ) ;
271
271
err = null ;
272
272
res = 'OK' ;
273
- } else if ( self . auth_callback ) {
274
- self . auth_callback ( err ) ;
275
- self . auth_callback = null ;
276
- return ;
277
273
} else {
278
274
self . emit ( 'error' , err ) ;
279
- return ;
280
275
}
281
- }
282
-
283
- res = res . toString ( ) ;
284
- debug ( 'Auth succeeded ' + self . address + ' id ' + self . connection_id ) ;
285
-
286
- if ( self . auth_callback ) {
287
- self . auth_callback ( null , res ) ;
288
- self . auth_callback = null ;
289
- }
290
-
291
- // Now we are really connected
292
- self . emit ( 'connect' ) ;
293
- self . initialize_retry_vars ( ) ;
294
-
295
- if ( self . options . no_ready_check ) {
296
- self . on_ready ( ) ;
297
276
} else {
298
- self . ready_check ( ) ;
277
+ debug ( 'Auth succeeded ' + self . address + ' id ' + self . connection_id ) ;
299
278
}
300
279
} ) ;
301
- self . send_anyway = false ;
280
+ this . send_anyway = false ;
302
281
} ;
303
282
304
283
RedisClient . prototype . on_connect = function ( ) {
305
284
debug ( 'Stream connected ' + this . address + ' id ' + this . connection_id ) ;
306
285
307
286
this . connected = true ;
308
287
this . ready = false ;
309
- this . connections += 1 ;
310
288
this . emitted_end = false ;
311
- if ( this . options . socket_nodelay ) {
312
- this . stream . setNoDelay ( ) ;
313
- }
314
289
this . stream . setKeepAlive ( this . options . socket_keepalive ) ;
315
290
this . stream . setTimeout ( 0 ) ;
316
291
317
- if ( typeof this . auth_pass === 'string' ) {
318
- this . do_auth ( ) ;
319
- } else {
320
- this . emit ( 'connect' ) ;
321
- this . initialize_retry_vars ( ) ;
292
+ this . emit ( 'connect' ) ;
293
+ this . initialize_retry_vars ( ) ;
322
294
323
- if ( this . options . no_ready_check ) {
324
- this . on_ready ( ) ;
325
- } else {
326
- this . ready_check ( ) ;
327
- }
295
+ if ( this . options . no_ready_check ) {
296
+ this . on_ready ( ) ;
297
+ } else {
298
+ this . ready_check ( ) ;
328
299
}
329
300
} ;
330
301
331
302
RedisClient . prototype . on_ready = function ( ) {
332
303
var self = this ;
333
304
305
+ debug ( 'on_ready called ' + this . address + ' id ' + this . connection_id ) ;
334
306
this . ready = true ;
335
307
336
308
if ( this . old_state !== null ) {
@@ -358,8 +330,8 @@ RedisClient.prototype.on_ready = function () {
358
330
}
359
331
this . cork = cork ;
360
332
361
- // magically restore any modal commands from a previous connection
362
- if ( this . selected_db !== null ) {
333
+ // restore modal commands from previous connection
334
+ if ( this . selected_db !== undefined ) {
363
335
// this trick works if and only if the following send_command
364
336
// never goes into the offline queue
365
337
var pub_sub_mode = this . pub_sub_mode ;
@@ -401,84 +373,43 @@ RedisClient.prototype.on_ready = function () {
401
373
RedisClient . prototype . on_info_cmd = function ( err , res ) {
402
374
if ( err ) {
403
375
if ( err . message === "ERR unknown command 'info'" ) {
404
- this . server_info = { } ;
405
376
this . on_ready ( ) ;
406
377
return ;
407
- } else {
408
- err . message = 'Ready check failed: ' + err . message ;
409
- this . emit ( 'error' , err ) ;
410
- return ;
411
- }
378
+ }
379
+ err . message = 'Ready check failed: ' + err . message ;
380
+ this . emit ( 'error' , err ) ;
381
+ return ;
412
382
}
413
383
414
384
/* istanbul ignore if: some servers might not respond with any info data. This is just a safety check that is difficult to test */
415
385
if ( ! res ) {
416
386
debug ( 'The info command returned without any data.' ) ;
417
- this . server_info = { } ;
418
387
this . on_ready ( ) ;
419
388
return ;
420
389
}
421
390
422
- var obj = { } ;
423
- var lines = res . toString ( ) . split ( '\r\n' ) ;
424
- var i = 0 ;
425
- var key = 'db' + i ;
426
- var line , retry_time , parts , sub_parts ;
427
-
428
- for ( i = 0 ; i < lines . length ; i ++ ) {
429
- parts = lines [ i ] . split ( ':' ) ;
430
- if ( parts [ 1 ] ) {
431
- obj [ parts [ 0 ] ] = parts [ 1 ] ;
432
- }
433
- }
434
-
435
- obj . versions = [ ] ;
436
- /* istanbul ignore else: some redis servers do not send the version */
437
- if ( obj . redis_version ) {
438
- obj . redis_version . split ( '.' ) . forEach ( function ( num ) {
439
- obj . versions . push ( + num ) ;
440
- } ) ;
441
- }
442
-
443
- while ( obj [ key ] ) {
444
- parts = obj [ key ] . split ( ',' ) ;
445
- obj [ key ] = { } ;
446
- while ( line = parts . pop ( ) ) {
447
- sub_parts = line . split ( '=' ) ;
448
- obj [ key ] [ sub_parts [ 0 ] ] = + sub_parts [ 1 ] ;
449
- }
450
- i ++ ;
451
- key = 'db' + i ;
452
- }
453
-
454
- // Expose info key/vals to users
455
- this . server_info = obj ;
456
-
457
- if ( ! obj . loading || obj . loading === '0' ) {
391
+ if ( ! this . server_info . loading || this . server_info . loading === '0' ) {
458
392
debug ( 'Redis server ready.' ) ;
459
393
this . on_ready ( ) ;
460
- } else {
461
- retry_time = obj . loading_eta_seconds * 1000 ;
462
- if ( retry_time > 1000 ) {
463
- retry_time = 1000 ;
464
- }
465
- debug ( 'Redis server still loading, trying again in ' + retry_time ) ;
466
- setTimeout ( function ( self ) {
467
- self . ready_check ( ) ;
468
- } , retry_time , this ) ;
394
+ return ;
395
+ }
396
+
397
+ var retry_time = + this . server_info . loading_eta_seconds * 1000 ;
398
+ if ( retry_time > 1000 ) {
399
+ retry_time = 1000 ;
469
400
}
401
+ debug ( 'Redis server still loading, trying again in ' + retry_time ) ;
402
+ setTimeout ( function ( self ) {
403
+ self . ready_check ( ) ;
404
+ } , retry_time , this ) ;
470
405
} ;
471
406
472
407
RedisClient . prototype . ready_check = function ( ) {
473
408
var self = this ;
474
-
475
409
debug ( 'Checking server ready state...' ) ;
476
-
477
- this . send_anyway = true ; // secret flag to send_command to send something even if not 'ready'
478
410
this . info ( function ( err , res ) {
479
411
self . on_info_cmd ( err , res ) ;
480
412
} ) ;
481
- this . send_anyway = false ;
482
413
} ;
483
414
484
415
RedisClient . prototype . send_offline_queue = function ( ) {
@@ -531,7 +462,7 @@ RedisClient.prototype.connection_gone = function (why) {
531
462
this . old_state = state ;
532
463
this . monitoring = false ;
533
464
this . pub_sub_mode = false ;
534
- this . selected_db = null ;
465
+ this . selected_db = undefined ;
535
466
}
536
467
537
468
// since we are collapsing end and close, users don't expect to be called twice
@@ -1010,6 +941,53 @@ RedisClient.prototype.select = RedisClient.prototype.SELECT = function (db, call
1010
941
} ) ;
1011
942
} ;
1012
943
944
+ // Store db in this.select_db to restore it on reconnect
945
+ RedisClient . prototype . info = RedisClient . prototype . INFO = function ( callback ) {
946
+ var self = this ;
947
+ this . send_anyway = true ;
948
+ var tmp = this . send_command ( 'info' , [ ] , function ( err , res ) {
949
+ if ( res ) {
950
+ var obj = { } ;
951
+ var lines = res . toString ( ) . split ( '\r\n' ) ;
952
+ var line , parts , sub_parts ;
953
+
954
+ for ( var i = 0 ; i < lines . length ; i ++ ) {
955
+ parts = lines [ i ] . split ( ':' ) ;
956
+ if ( parts [ 1 ] ) {
957
+ if ( parts [ 0 ] . indexOf ( 'db' ) === 0 ) {
958
+ sub_parts = parts [ 1 ] . split ( ',' ) ;
959
+ obj [ parts [ 0 ] ] = { } ;
960
+ while ( line = sub_parts . pop ( ) ) {
961
+ line = line . split ( '=' ) ;
962
+ obj [ parts [ 0 ] ] [ line [ 0 ] ] = + line [ 1 ] ;
963
+ }
964
+ } else {
965
+ obj [ parts [ 0 ] ] = parts [ 1 ] ;
966
+ }
967
+ }
968
+ }
969
+ obj . versions = [ ] ;
970
+ /* istanbul ignore else: some redis servers do not send the version */
971
+ if ( obj . redis_version ) {
972
+ obj . redis_version . split ( '.' ) . forEach ( function ( num ) {
973
+ obj . versions . push ( + num ) ;
974
+ } ) ;
975
+ }
976
+ // Expose info key/vals to users
977
+ self . server_info = obj ;
978
+ } else {
979
+ self . server_info = { } ;
980
+ }
981
+ if ( typeof callback === 'function' ) {
982
+ callback ( err , res ) ;
983
+ } else if ( err ) {
984
+ self . emit ( 'error' , err ) ;
985
+ }
986
+ } ) ;
987
+ this . send_anyway = false ;
988
+ return tmp ;
989
+ } ;
990
+
1013
991
RedisClient . prototype . callback_emit_error = function ( callback , err ) {
1014
992
if ( callback ) {
1015
993
setImmediate ( function ( ) {
@@ -1030,12 +1008,10 @@ RedisClient.prototype.auth = RedisClient.prototype.AUTH = function (pass, callba
1030
1008
}
1031
1009
this . auth_pass = pass ;
1032
1010
debug ( 'Saving auth as ' + this . auth_pass ) ;
1033
- // Only run the callback once. So do not safe it if already connected
1034
- if ( this . connected ) {
1035
- return this . send_command ( 'auth' , [ this . auth_pass ] , callback ) ;
1036
- }
1037
- this . auth_callback = callback ;
1038
- return true ;
1011
+ this . send_anyway = true ;
1012
+ var tmp = this . send_command ( 'auth' , [ pass ] , callback ) ;
1013
+ this . send_anyway = false ;
1014
+ return tmp ;
1039
1015
} ;
1040
1016
1041
1017
RedisClient . prototype . hmset = RedisClient . prototype . HMSET = function ( key , args , callback ) {
0 commit comments