Skip to content

Commit d5de30a

Browse files
committed
refactor: extract handshake
1 parent ba1b104 commit d5de30a

File tree

1 file changed

+78
-77
lines changed

1 file changed

+78
-77
lines changed

packages/client/lib/client/index.ts

Lines changed: 78 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ClientClosedError, ClientOfflineError, DisconnectsClientError, SimpleEr
88
import { URL } from 'node:url';
99
import { TcpSocketConnectOpts } from 'node:net';
1010
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';
1212
import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command';
1313
import { RedisMultiQueuedCommand } from '../multi-command';
1414
import HELLO, { HelloOptions } from '../commands/HELLO';
@@ -446,7 +446,30 @@ export default class RedisClient<
446446
});
447447
}
448448

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+
> {
450473
const commands = [];
451474
const cp = this.#options?.credentialsProvider;
452475

@@ -464,8 +487,8 @@ export default class RedisClient<
464487
}
465488

466489
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);
469492
this.#credentialsSubscription = disposable;
470493

471494
if (credentials.password) {
@@ -480,55 +503,84 @@ export default class RedisClient<
480503
hello.SETNAME = this.#options.name;
481504
}
482505

483-
commands.push(
484-
parseArgs(HELLO, this.#options.RESP, hello)
485-
);
506+
commands.push({ cmd: parseArgs(HELLO, this.#options.RESP, hello) });
486507
} else {
487-
488508
if (cp && cp.type === 'async-credentials-provider') {
489-
490509
const credentials = await cp.credentials();
491510

492511
if (credentials.username || credentials.password) {
493-
commands.push(
494-
parseArgs(COMMANDS.AUTH, {
512+
commands.push({
513+
cmd: parseArgs(COMMANDS.AUTH, {
495514
username: credentials.username,
496515
password: credentials.password ?? ''
497516
})
498-
);
517+
});
499518
}
500519
}
501520

502521
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);
505524
this.#credentialsSubscription = disposable;
506525

507526
if (credentials.username || credentials.password) {
508-
commands.push(
509-
parseArgs(COMMANDS.AUTH, {
527+
commands.push({
528+
cmd: parseArgs(COMMANDS.AUTH, {
510529
username: credentials.username,
511530
password: credentials.password ?? ''
512531
})
513-
);
532+
});
514533
}
515534
}
516535

517536
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+
});
521540
}
522541
}
523542

524543
if (selectedDB !== 0) {
525-
commands.push(['SELECT', this.#selectedDB.toString()]);
544+
commands.push({ cmd: ['SELECT', this.#selectedDB.toString()] });
526545
}
527546

528547
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+
});
532584
}
533585

534586
return commands;
@@ -557,52 +609,7 @@ export default class RedisClient<
557609
);
558610
}
559611

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)));
606613

607614
if (promises.length) {
608615
this.#write();
@@ -1179,13 +1186,7 @@ export default class RedisClient<
11791186
selectedDB = this._self.#options?.database ?? 0;
11801187
this._self.#credentialsSubscription?.dispose();
11811188
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)));
11891190
this._self.#scheduleWrite();
11901191
await Promise.all(promises);
11911192
this._self.#selectedDB = selectedDB;

0 commit comments

Comments
 (0)