From a65b1f9b31f37aed76aff08a734b36c360cb64ab Mon Sep 17 00:00:00 2001 From: Bronika Brisbon Date: Wed, 23 Apr 2025 15:38:03 +0200 Subject: [PATCH] add + use option commandTimeout --- packages/client/lib/client/index.spec.ts | 1 + packages/client/lib/client/index.ts | 30 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index c71cf1a1fad..096c17f1cb4 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -34,6 +34,7 @@ describe('Client', () => { }, username: 'user', password: 'secret', + commandTimeout: 1000, database: 0, credentialsProvider: { type: 'async-credentials-provider', diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 5dae1271ecb..73224ca5237 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -80,6 +80,10 @@ export interface RedisClientOptions< * TODO */ commandOptions?: CommandOptions; + /** + * Provides a timeout in milliseconds. + */ + commandTimeout?: number; } type WithCommands< @@ -678,19 +682,43 @@ export default class RedisClient< /** * @internal */ - async _executeCommand( + async _executeCommand( command: Command, parser: CommandParser, commandOptions: CommandOptions | undefined, transformReply: TransformReply | undefined, ) { + // If no timeout is set, execute the command normally + if (!this._self.#options?.commandTimeout) { const reply = await this.sendCommand(parser.redisArgs, commandOptions); + if (transformReply) { return transformReply(reply, parser.preserve, commandOptions?.typeMapping); } return reply; + } + + // Wrap the command execution in a timeout + return new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + reject(new Error(`Command timed out after ${this._self.#options?.commandTimeout}ms`)); + }, this._self.#options?.commandTimeout); + + this.sendCommand(parser.redisArgs, commandOptions) + .then(reply => { + clearTimeout(timeoutId); // Clear the timeout if the command succeeds + const transformedReply = transformReply + ? transformReply(reply, parser.preserve, commandOptions?.typeMapping) + : reply; + resolve(transformedReply); + }) + .catch(err => { + clearTimeout(timeoutId); // Clear the timeout if the command fails + reject(err); + }); + }); } /**