@@ -8,7 +8,7 @@ import { ClientClosedError, ClientOfflineError, DisconnectsClientError, SimpleEr
8
8
import { URL } from 'node:url' ;
9
9
import { TcpSocketConnectOpts } from 'node:net' ;
10
10
import { PUBSUB_TYPE , PubSubType , PubSubListener , PubSubTypeListeners , ChannelListeners } from './pub-sub' ;
11
- import { Command , CommandSignature , TypeMapping , CommanderConfig , RedisFunction , RedisFunctions , RedisModules , RedisScript , RedisScripts , ReplyUnion , RespVersions , RedisArgument , ReplyWithTypeMapping , SimpleStringReply , TransformReply } from '../RESP/types' ;
11
+ import { Command , CommandSignature , TypeMapping , CommanderConfig , RedisFunction , RedisFunctions , RedisModules , RedisScript , RedisScripts , ReplyUnion , RespVersions , RedisArgument , ReplyWithTypeMapping , SimpleStringReply , TransformReply , CommandArguments } from '../RESP/types' ;
12
12
import RedisClientMultiCommand , { RedisClientMultiCommandType } from './multi-command' ;
13
13
import { RedisMultiQueuedCommand } from '../multi-command' ;
14
14
import HELLO , { HelloOptions } from '../commands/HELLO' ;
@@ -446,7 +446,30 @@ export default class RedisClient<
446
446
} ) ;
447
447
}
448
448
449
- async #handshake( selectedDB : number ) {
449
+ async #handshake( chainId : symbol , asap : boolean ) {
450
+ const promises = [ ] ;
451
+ const commandsWithErrorHandlers = await this . #getHandshakeCommands( this . #selectedDB ?? 0 ) ;
452
+
453
+ if ( asap ) commandsWithErrorHandlers . reverse ( )
454
+
455
+ for ( const { cmd, errorHandler } of commandsWithErrorHandlers ) {
456
+ promises . push (
457
+ this . #queue
458
+ . addCommand ( cmd , {
459
+ chainId,
460
+ asap
461
+ } )
462
+ . catch ( errorHandler )
463
+ ) ;
464
+ }
465
+ return promises ;
466
+ }
467
+
468
+ async #getHandshakeCommands(
469
+ selectedDB : number
470
+ ) : Promise <
471
+ Array < { cmd : CommandArguments } & { errorHandler ?: ( err : Error ) => void } >
472
+ > {
450
473
const commands = [ ] ;
451
474
const cp = this . #options?. credentialsProvider ;
452
475
@@ -464,8 +487,8 @@ export default class RedisClient<
464
487
}
465
488
466
489
if ( cp && cp . type === 'streaming-credentials-provider' ) {
467
-
468
- const [ credentials , disposable ] = await this . #subscribeForStreamingCredentials( cp )
490
+ const [ credentials , disposable ] =
491
+ await this . #subscribeForStreamingCredentials( cp ) ;
469
492
this . #credentialsSubscription = disposable ;
470
493
471
494
if ( credentials . password ) {
@@ -480,55 +503,84 @@ export default class RedisClient<
480
503
hello . SETNAME = this . #options. name ;
481
504
}
482
505
483
- commands . push (
484
- parseArgs ( HELLO , this . #options. RESP , hello )
485
- ) ;
506
+ commands . push ( { cmd : parseArgs ( HELLO , this . #options. RESP , hello ) } ) ;
486
507
} else {
487
-
488
508
if ( cp && cp . type === 'async-credentials-provider' ) {
489
-
490
509
const credentials = await cp . credentials ( ) ;
491
510
492
511
if ( credentials . username || credentials . password ) {
493
- commands . push (
494
- parseArgs ( COMMANDS . AUTH , {
512
+ commands . push ( {
513
+ cmd : parseArgs ( COMMANDS . AUTH , {
495
514
username : credentials . username ,
496
515
password : credentials . password ?? ''
497
516
} )
498
- ) ;
517
+ } ) ;
499
518
}
500
519
}
501
520
502
521
if ( cp && cp . type === 'streaming-credentials-provider' ) {
503
-
504
- const [ credentials , disposable ] = await this . #subscribeForStreamingCredentials( cp )
522
+ const [ credentials , disposable ] =
523
+ await this . #subscribeForStreamingCredentials( cp ) ;
505
524
this . #credentialsSubscription = disposable ;
506
525
507
526
if ( credentials . username || credentials . password ) {
508
- commands . push (
509
- parseArgs ( COMMANDS . AUTH , {
527
+ commands . push ( {
528
+ cmd : parseArgs ( COMMANDS . AUTH , {
510
529
username : credentials . username ,
511
530
password : credentials . password ?? ''
512
531
} )
513
- ) ;
532
+ } ) ;
514
533
}
515
534
}
516
535
517
536
if ( this . #options?. name ) {
518
- commands . push (
519
- parseArgs ( COMMANDS . CLIENT_SETNAME , this . #options. name )
520
- ) ;
537
+ commands . push ( {
538
+ cmd : parseArgs ( COMMANDS . CLIENT_SETNAME , this . #options. name )
539
+ } ) ;
521
540
}
522
541
}
523
542
524
543
if ( selectedDB !== 0 ) {
525
- commands . push ( [ 'SELECT' , this . #selectedDB. toString ( ) ] ) ;
544
+ commands . push ( { cmd : [ 'SELECT' , this . #selectedDB. toString ( ) ] } ) ;
526
545
}
527
546
528
547
if ( this . #options?. readonly ) {
529
- commands . push (
530
- parseArgs ( COMMANDS . READONLY )
531
- ) ;
548
+ commands . push ( { cmd : parseArgs ( COMMANDS . READONLY ) } ) ;
549
+ }
550
+
551
+ if ( ! this . #options?. disableClientInfo ) {
552
+ commands . push ( {
553
+ cmd : [ 'CLIENT' , 'SETINFO' , 'LIB-VER' , version ] ,
554
+ errorHandler : ( err : Error ) => {
555
+ // Only throw if not a SimpleError - unknown subcommand
556
+ // Client libraries are expected to ignore failures
557
+ // of type SimpleError - unknown subcommand, which are
558
+ // expected from older servers ( < v7 )
559
+ if ( ! ( err instanceof SimpleError ) || ! err . isUnknownSubcommand ( ) ) {
560
+ throw err ;
561
+ }
562
+ }
563
+ } ) ;
564
+
565
+ commands . push ( {
566
+ cmd : [
567
+ 'CLIENT' ,
568
+ 'SETINFO' ,
569
+ 'LIB-NAME' ,
570
+ this . #options?. clientInfoTag
571
+ ? `node-redis(${ this . #options. clientInfoTag } )`
572
+ : 'node-redis'
573
+ ] ,
574
+ errorHandler : ( err : Error ) => {
575
+ // Only throw if not a SimpleError - unknown subcommand
576
+ // Client libraries are expected to ignore failures
577
+ // of type SimpleError - unknown subcommand, which are
578
+ // expected from older servers ( < v7 )
579
+ if ( ! ( err instanceof SimpleError ) || ! err . isUnknownSubcommand ( ) ) {
580
+ throw err ;
581
+ }
582
+ }
583
+ } ) ;
532
584
}
533
585
534
586
return commands ;
@@ -557,52 +609,7 @@ export default class RedisClient<
557
609
) ;
558
610
}
559
611
560
- if ( ! this . #options?. disableClientInfo ) {
561
- promises . push (
562
- this . #queue. addCommand ( [
563
- 'CLIENT' ,
564
- 'SETINFO' ,
565
- 'LIB-NAME' ,
566
- this . #options?. clientInfoTag
567
- ? `node-redis(${ this . #options. clientInfoTag } )` : 'node-redis'
568
- ] , {
569
- chainId,
570
- asap : true
571
- } ) . catch ( err => {
572
- // Only throw if not a SimpleError - unknown subcommand
573
- // Client libraries are expected to ignore failures
574
- // of type SimpleError - unknown subcommand, which are
575
- // expected from older servers ( < v7 )
576
- if ( ! ( err instanceof SimpleError ) || ! err . isUnknownSubcommand ( ) ) {
577
- throw err ;
578
- }
579
- } )
580
- ) ;
581
- promises . push (
582
- this . #queue. addCommand ( [ 'CLIENT' , 'SETINFO' , 'LIB-VER' , version ] , {
583
- chainId,
584
- asap : true
585
- } ) . catch ( err => {
586
- // Only throw if not a SimpleError - unknown subcommand
587
- // Client libraries are expected to ignore failures
588
- // of type SimpleError - unknown subcommand, which are
589
- // expected from older servers ( < v7 )
590
- if ( ! ( err instanceof SimpleError ) || ! err . isUnknownSubcommand ( ) ) {
591
- throw err ;
592
- }
593
- } )
594
- ) ;
595
- }
596
-
597
- const commands = await this . #handshake( this . #selectedDB) ;
598
- for ( let i = commands . length - 1 ; i >= 0 ; -- i ) {
599
- promises . push (
600
- this . #queue. addCommand ( commands [ i ] , {
601
- chainId,
602
- asap : true
603
- } )
604
- ) ;
605
- }
612
+ promises . push ( ...( await this . #handshake( chainId , true ) ) ) ;
606
613
607
614
if ( promises . length ) {
608
615
this . #write( ) ;
@@ -1179,13 +1186,7 @@ export default class RedisClient<
1179
1186
selectedDB = this . _self . #options?. database ?? 0 ;
1180
1187
this . _self . #credentialsSubscription?. dispose ( ) ;
1181
1188
this . _self . #credentialsSubscription = null ;
1182
- for ( const command of ( await this . _self . #handshake( selectedDB ) ) ) {
1183
- promises . push (
1184
- this . _self . #queue. addCommand ( command , {
1185
- chainId
1186
- } )
1187
- ) ;
1188
- }
1189
+ promises . push ( ...( await this . _self . #handshake( chainId , false ) ) ) ;
1189
1190
this . _self . #scheduleWrite( ) ;
1190
1191
await Promise . all ( promises ) ;
1191
1192
this . _self . #selectedDB = selectedDB ;
0 commit comments