From 288ecfd706bafcaa43dc0916b986d121c088c8a5 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 26 Aug 2025 16:37:00 -0700 Subject: [PATCH 1/9] fix(redis): treat intermittent errors as warnings Signed-off-by: Aramis Sennyey --- .../rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts index effa7ec8cf2..a7479aec6db 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts @@ -56,6 +56,10 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { } catch (e) { throw new Error(`Failed to create redis client: ${e.message}`); } + // Register error event handler to avoid process exit when redis client error occurs. + this._redisClient.on('error', (e: Error) => { + this._terminal.writeErrorLine(`Redis client error: ${e.message}`); + }); } public static expandOptionsWithEnvironmentVariables( From 1ac289eea513ec46c6c81d131a6ac9545644e892 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 26 Aug 2025 16:38:13 -0700 Subject: [PATCH 2/9] add changeset Signed-off-by: Aramis Sennyey --- .../sennyeya-fix-redis-error_2025-08-26-23-37.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json diff --git a/common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json b/common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json new file mode 100644 index 00000000000..4291c802bf4 --- /dev/null +++ b/common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "Treat intermittent ignored errors as warnings and allow build to continue.", + "type": "none", + "packageName": "@microsoft/rush" + } + ], + "packageName": "@microsoft/rush", + "email": "aramissennyeydd@users.noreply.github.com" +} \ No newline at end of file From 05e9483a5b0e6c318791af6a270b4d71328247ee Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 26 Aug 2025 17:26:09 -0700 Subject: [PATCH 3/9] fix(rush): intermittent redis errors Signed-off-by: Aramis Sennyey --- .../config/subspaces/default/pnpm-lock.yaml | 17 +++------- .../config/subspaces/default/repo-state.json | 2 +- .../api/rush-redis-cobuild-plugin.api.md | 5 ++- .../rush-redis-cobuild-plugin/package.json | 2 +- .../src/RedisCobuildLockProvider.ts | 33 ++++++++++++++----- .../src/test/RedisCobuildLockProvider.test.ts | 7 +++- 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index b9ceb1be59b..85393b99174 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -4557,8 +4557,8 @@ importers: ../../../rush-plugins/rush-redis-cobuild-plugin: dependencies: '@redis/client': - specifier: ~1.5.5 - version: 1.5.14 + specifier: ~5.8.2 + version: 5.8.2 '@rushstack/node-core-library': specifier: workspace:* version: link:../../libraries/node-core-library @@ -11047,13 +11047,11 @@ packages: react: 17.0.2 dev: true - /@redis/client@1.5.14: - resolution: {integrity: sha512-YGn0GqsRBFUQxklhY7v562VMOP0DcmlrHHs3IV1mFE3cbxe31IITUkqhBcIhVSI/2JqtWAJXg5mjV4aU+zD0HA==} - engines: {node: '>=14'} + /@redis/client@5.8.2: + resolution: {integrity: sha512-WtMScno3+eBpTac1Uav2zugXEoXqaU23YznwvFgkPwBQVwEHTDgOG7uEAObtZ/Nyn8SmAMbqkEubJaMOvnqdsQ==} + engines: {node: '>= 18'} dependencies: cluster-key-slot: 1.1.2 - generic-pool: 3.9.0 - yallist: 4.0.0 dev: false /@reduxjs/toolkit@1.8.6(react-redux@8.0.7)(react@17.0.2): @@ -21070,11 +21068,6 @@ packages: loader-utils: 3.2.1 dev: false - /generic-pool@3.9.0: - resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} - engines: {node: '>= 4'} - dev: false - /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index eb22dd89def..9b98d794324 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "c643d2cc7e2c60ef034a6557fc89760140d42f66", + "pnpmShrinkwrapHash": "e0b573b05fff66c7c9e7ae104e8a2f863ef58864", "preferredVersionsHash": "61cd419c533464b580f653eb5f5a7e27fe7055ca" } diff --git a/common/reviews/api/rush-redis-cobuild-plugin.api.md b/common/reviews/api/rush-redis-cobuild-plugin.api.md index a28011c7be2..19f2ae4a52c 100644 --- a/common/reviews/api/rush-redis-cobuild-plugin.api.md +++ b/common/reviews/api/rush-redis-cobuild-plugin.api.md @@ -11,11 +11,14 @@ import type { ICobuildContext } from '@rushstack/rush-sdk'; import type { ICobuildLockProvider } from '@rushstack/rush-sdk'; import type { IRushPlugin } from '@rushstack/rush-sdk'; import type { RedisClientOptions } from '@redis/client'; +import type { RedisFunctions } from '@redis/client'; +import type { RedisModules } from '@redis/client'; +import type { RedisScripts } from '@redis/client'; import type { RushConfiguration } from '@rushstack/rush-sdk'; import type { RushSession } from '@rushstack/rush-sdk'; // @beta -export interface IRedisCobuildLockProviderOptions extends RedisClientOptions { +export interface IRedisCobuildLockProviderOptions extends RedisClientOptions { passwordEnvironmentVariable?: string; } diff --git a/rush-plugins/rush-redis-cobuild-plugin/package.json b/rush-plugins/rush-redis-cobuild-plugin/package.json index 1d4ae446141..49102c4e98e 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/package.json +++ b/rush-plugins/rush-redis-cobuild-plugin/package.json @@ -19,7 +19,7 @@ "_phase:test": "heft run --only test -- --clean" }, "dependencies": { - "@redis/client": "~1.5.5", + "@redis/client": "~5.8.2", "@rushstack/node-core-library": "workspace:*", "@rushstack/rush-sdk": "workspace:*" }, diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts index a7479aec6db..6bd88576dbd 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts @@ -7,7 +7,8 @@ import type { RedisClientType, RedisFunctions, RedisModules, - RedisScripts + RedisScripts, + TypeMapping } from '@redis/client'; import type { @@ -22,7 +23,8 @@ import type { ITerminal } from '@rushstack/terminal'; * The redis client options * @beta */ -export interface IRedisCobuildLockProviderOptions extends RedisClientOptions { +export interface IRedisCobuildLockProviderOptions + extends RedisClientOptions { /** * The environment variable name for the redis password */ @@ -46,20 +48,24 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { string >(); - private readonly _redisClient: RedisClientType; + private readonly _redisClient: RedisClientType; public constructor(options: IRedisCobuildLockProviderOptions, rushSession: RushSession) { this._options = RedisCobuildLockProvider.expandOptionsWithEnvironmentVariables(options); this._terminal = rushSession.getLogger('RedisCobuildLockProvider').terminal; try { - this._redisClient = createClient(this._options); + this._redisClient = createClient({ + ...this._options, + socket: { + reconnectStrategy: (count: number) => { + this._terminal.writeErrorLine(`Redis client reconnecting attempt #${count}`); + return count < 5 ? count * 1000 : false; + } + } + }); } catch (e) { throw new Error(`Failed to create redis client: ${e.message}`); } - // Register error event handler to avoid process exit when redis client error occurs. - this._redisClient.on('error', (e: Error) => { - this._terminal.writeErrorLine(`Redis client error: ${e.message}`); - }); } public static expandOptionsWithEnvironmentVariables( @@ -99,11 +105,20 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { } catch (e) { throw new Error(`Failed to connect to redis server: ${e.message}`); } + + // Register error event handler to avoid process exit when redis client error occurs. + this._redisClient.on('error', (e: Error) => { + if (e.message) { + this._terminal.writeErrorLine(`Redis client error: ${e.message}`); + } else { + this._terminal.writeErrorLine(`Redis client error: ${e}`); + } + }); } public async disconnectAsync(): Promise { try { - await this._redisClient.disconnect(); + await this._redisClient.quit(); } catch (e) { throw new Error(`Failed to disconnect to redis server: ${e.message}`); } diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts b/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts index 3fa6cf43c02..ede5f15c7f1 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts @@ -58,7 +58,12 @@ describe(RedisCobuildLockProvider.name, () => { get: jest.fn().mockImplementation((key: string) => { return storage[key]; }) - } as unknown as RedisClientType; + } as unknown as RedisClientType< + redisAPI.RedisModules, + redisAPI.RedisFunctions, + redisAPI.RedisScripts, + 2 | 3 + >; }); }); From 21371551b6c99fd12fb990d66955f1065fb32180 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 26 Aug 2025 17:29:04 -0700 Subject: [PATCH 4/9] fix lint + move ordering Signed-off-by: Aramis Sennyey --- .../src/RedisCobuildLockProvider.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts index 6bd88576dbd..f6f0c910ccc 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts @@ -7,8 +7,7 @@ import type { RedisClientType, RedisFunctions, RedisModules, - RedisScripts, - TypeMapping + RedisScripts } from '@redis/client'; import type { @@ -52,16 +51,18 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { public constructor(options: IRedisCobuildLockProviderOptions, rushSession: RushSession) { this._options = RedisCobuildLockProvider.expandOptionsWithEnvironmentVariables(options); + // Provide a default reconnect strategy that prevents more than 5 reconnect attempts. + this._options.socket = { + reconnectStrategy: (count: number) => { + this._terminal.writeErrorLine(`Redis client reconnecting attempt #${count}`); + return count < 5 ? count * 1000 : false; + }, + ...this._options.socket + }; this._terminal = rushSession.getLogger('RedisCobuildLockProvider').terminal; try { this._redisClient = createClient({ - ...this._options, - socket: { - reconnectStrategy: (count: number) => { - this._terminal.writeErrorLine(`Redis client reconnecting attempt #${count}`); - return count < 5 ? count * 1000 : false; - } - } + ...this._options }); } catch (e) { throw new Error(`Failed to create redis client: ${e.message}`); @@ -73,6 +74,7 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { environment: NodeJS.ProcessEnv = process.env ): IRedisCobuildLockProviderOptions { const finalOptions: IRedisCobuildLockProviderOptions = { ...options }; + const missingEnvironmentVariables: Set = new Set(); if (finalOptions.passwordEnvironmentVariable) { From d8a2bca8b2c6d83990f96831ed3d62f43c7b0772 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:38:21 -0700 Subject: [PATCH 5/9] Apply suggestions from code review --- .../src/RedisCobuildLockProvider.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts index f6f0c910ccc..19c16767dd4 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts @@ -61,9 +61,7 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { }; this._terminal = rushSession.getLogger('RedisCobuildLockProvider').terminal; try { - this._redisClient = createClient({ - ...this._options - }); + this._redisClient = createClient(this._options); } catch (e) { throw new Error(`Failed to create redis client: ${e.message}`); } @@ -74,7 +72,6 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { environment: NodeJS.ProcessEnv = process.env ): IRedisCobuildLockProviderOptions { const finalOptions: IRedisCobuildLockProviderOptions = { ...options }; - const missingEnvironmentVariables: Set = new Set(); if (finalOptions.passwordEnvironmentVariable) { From 2c563b219f3b3e3ec2f675831f79898c55982774 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 26 Aug 2025 17:40:55 -0700 Subject: [PATCH 6/9] destroy the client Signed-off-by: Aramis Sennyey --- .../rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts index 19c16767dd4..53e226d7117 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts @@ -117,7 +117,7 @@ export class RedisCobuildLockProvider implements ICobuildLockProvider { public async disconnectAsync(): Promise { try { - await this._redisClient.quit(); + await this._redisClient.destroy(); } catch (e) { throw new Error(`Failed to disconnect to redis server: ${e.message}`); } From e932a2b5fac77d2ca53ccf4c3a31b1725f45c1aa Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 26 Aug 2025 17:42:50 -0700 Subject: [PATCH 7/9] fix types Signed-off-by: Aramis Sennyey --- .../src/RedisCobuildLockProvider.ts | 3 +-- .../src/test/RedisCobuildLockProvider.test.ts | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts index 53e226d7117..3c2398baca8 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/RedisCobuildLockProvider.ts @@ -22,8 +22,7 @@ import type { ITerminal } from '@rushstack/terminal'; * The redis client options * @beta */ -export interface IRedisCobuildLockProviderOptions - extends RedisClientOptions { +export interface IRedisCobuildLockProviderOptions extends RedisClientOptions { /** * The environment variable name for the redis password */ diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts b/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts index ede5f15c7f1..3fa6cf43c02 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts @@ -58,12 +58,7 @@ describe(RedisCobuildLockProvider.name, () => { get: jest.fn().mockImplementation((key: string) => { return storage[key]; }) - } as unknown as RedisClientType< - redisAPI.RedisModules, - redisAPI.RedisFunctions, - redisAPI.RedisScripts, - 2 | 3 - >; + } as unknown as RedisClientType; }); }); From c0b91e7edc4ea0014a169fcaa71812bb6368a1be Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 26 Aug 2025 17:44:33 -0700 Subject: [PATCH 8/9] fix api report + test build Signed-off-by: Aramis Sennyey --- common/reviews/api/rush-redis-cobuild-plugin.api.md | 5 +---- .../src/test/RedisCobuildLockProvider.test.ts | 7 ++++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/common/reviews/api/rush-redis-cobuild-plugin.api.md b/common/reviews/api/rush-redis-cobuild-plugin.api.md index 19f2ae4a52c..a28011c7be2 100644 --- a/common/reviews/api/rush-redis-cobuild-plugin.api.md +++ b/common/reviews/api/rush-redis-cobuild-plugin.api.md @@ -11,14 +11,11 @@ import type { ICobuildContext } from '@rushstack/rush-sdk'; import type { ICobuildLockProvider } from '@rushstack/rush-sdk'; import type { IRushPlugin } from '@rushstack/rush-sdk'; import type { RedisClientOptions } from '@redis/client'; -import type { RedisFunctions } from '@redis/client'; -import type { RedisModules } from '@redis/client'; -import type { RedisScripts } from '@redis/client'; import type { RushConfiguration } from '@rushstack/rush-sdk'; import type { RushSession } from '@rushstack/rush-sdk'; // @beta -export interface IRedisCobuildLockProviderOptions extends RedisClientOptions { +export interface IRedisCobuildLockProviderOptions extends RedisClientOptions { passwordEnvironmentVariable?: string; } diff --git a/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts b/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts index 3fa6cf43c02..ede5f15c7f1 100644 --- a/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts +++ b/rush-plugins/rush-redis-cobuild-plugin/src/test/RedisCobuildLockProvider.test.ts @@ -58,7 +58,12 @@ describe(RedisCobuildLockProvider.name, () => { get: jest.fn().mockImplementation((key: string) => { return storage[key]; }) - } as unknown as RedisClientType; + } as unknown as RedisClientType< + redisAPI.RedisModules, + redisAPI.RedisFunctions, + redisAPI.RedisScripts, + 2 | 3 + >; }); }); From 232e516867381ac3f93581d5bb037bc7edc42aef Mon Sep 17 00:00:00 2001 From: Ian Clanton-Thuon Date: Tue, 7 Oct 2025 12:33:50 -0700 Subject: [PATCH 9/9] Apply suggestion from @iclanton --- .../rush/sennyeya-fix-redis-error_2025-08-26-23-37.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json b/common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json index 4291c802bf4..16ad45039d3 100644 --- a/common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json +++ b/common/changes/@microsoft/rush/sennyeya-fix-redis-error_2025-08-26-23-37.json @@ -1,7 +1,7 @@ { "changes": [ { - "comment": "Treat intermittent ignored errors as warnings and allow build to continue.", + "comment": "Treat intermittent ignored redis errors as warnings and allow build to continue.", "type": "none", "packageName": "@microsoft/rush" }