From bf80c163b1305a859baa3dbc0bd6488c300e7a4f Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Thu, 26 May 2022 09:55:47 -0400 Subject: [PATCH] fix #2046 - add support for multi in select (#2133) * fix #2046 - add support for multi in select * fix "Argument of type 'symbol | undefined' is not assignable to parameter of type 'number | undefined'" --- packages/client/lib/client/index.spec.ts | 14 ++++++++++ packages/client/lib/client/index.ts | 18 ++++++++---- packages/client/lib/client/multi-command.ts | 31 ++++++++++++++++----- packages/client/lib/cluster/index.ts | 2 +- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 0b5fd05b9b..442b10ef52 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -468,6 +468,20 @@ describe('Client', () => { ['PONG'] ); }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('should remember selected db', async client => { + await client.multi() + .select(1) + .exec(); + await killClient(client); + assert.equal( + (await client.clientInfo()).db, + 1 + ); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [6, 2] // CLIENT INFO + }); }); testUtils.testWithClient('scripts', async client => { diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index fb86908bd2..9664b3645b 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -606,18 +606,26 @@ export default class RedisClient< ); } - multiExecutor(commands: Array, chainId?: symbol): Promise> { + async multiExecutor( + commands: Array, + selectedDB?: number, + chainId?: symbol + ): Promise> { const promise = Promise.all( commands.map(({ args }) => { - return this.#queue.addCommand(args, RedisClient.commandOptions({ - chainId - })); + return this.#queue.addCommand(args, { chainId }); }) ); this.#tick(); - return promise; + const results = await promise; + + if (selectedDB !== undefined) { + this.#selectedDB = selectedDB; + } + + return results; } async* scanIterator(options?: ScanCommandOptions): AsyncIterable { diff --git a/packages/client/lib/client/multi-command.ts b/packages/client/lib/client/multi-command.ts index 2eea429abe..1d6df1a483 100644 --- a/packages/client/lib/client/multi-command.ts +++ b/packages/client/lib/client/multi-command.ts @@ -58,13 +58,13 @@ type InstantiableRedisMultiCommand< S extends RedisScripts > = new (...args: ConstructorParameters) => RedisClientMultiCommandType; - -export type RedisClientMultiExecutor = (queue: Array, chainId?: symbol) => Promise>; +export type RedisClientMultiExecutor = ( + queue: Array, + selectedDB?: number, + chainId?: symbol +) => Promise>; export default class RedisClientMultiCommand { - readonly #multi = new RedisMultiCommand(); - readonly #executor: RedisClientMultiExecutor; - static extend< M extends RedisModules, F extends RedisFunctions, @@ -81,7 +81,10 @@ export default class RedisClientMultiCommand { }); } + readonly #multi = new RedisMultiCommand(); + readonly #executor: RedisClientMultiExecutor; readonly v4: Record = {}; + #selectedDB?: number; constructor(executor: RedisClientMultiExecutor, legacyMode = false) { this.#executor = executor; @@ -136,6 +139,13 @@ export default class RedisClientMultiCommand { ); } + SELECT(db: number, transformReply?: RedisCommand['transformReply']): this { + this.#selectedDB = db; + return this.addCommand(['SELECT', db.toString()], transformReply); + } + + select = this.SELECT; + addCommand(args: RedisCommandArguments, transformReply?: RedisCommand['transformReply']): this { this.#multi.addCommand(args, transformReply); return this; @@ -160,7 +170,11 @@ export default class RedisClientMultiCommand { if (!commands) return []; return this.#multi.handleExecReplies( - await this.#executor(commands, RedisMultiCommand.generateChainId()) + await this.#executor( + commands, + this.#selectedDB, + RedisMultiCommand.generateChainId() + ) ); } @@ -168,7 +182,10 @@ export default class RedisClientMultiCommand { async execAsPipeline(): Promise> { return this.#multi.transformReplies( - await this.#executor(this.#multi.queue) + await this.#executor( + this.#multi.queue, + this.#selectedDB + ) ); } } diff --git a/packages/client/lib/cluster/index.ts b/packages/client/lib/cluster/index.ts index f1a4cb42af..57ec6ff705 100644 --- a/packages/client/lib/cluster/index.ts +++ b/packages/client/lib/cluster/index.ts @@ -230,7 +230,7 @@ export default class RedisCluster< return this.#execute( firstKey, false, - client => client.multiExecutor(commands, chainId) + client => client.multiExecutor(commands, undefined, chainId) ); }, routing