From 228ebd6454a5172d83f43ac645c6b09b157090eb Mon Sep 17 00:00:00 2001 From: 777genius Date: Sun, 31 May 2026 07:47:16 +0300 Subject: [PATCH] perf(main): cache runtime command arg matches --- .../team/TeamRuntimeLivenessResolver.ts | 57 ++++++++++++++++++- .../team/TeamRuntimeLivenessResolver.test.ts | 10 ++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/main/services/team/TeamRuntimeLivenessResolver.ts b/src/main/services/team/TeamRuntimeLivenessResolver.ts index 77d6f896..553d7b82 100644 --- a/src/main/services/team/TeamRuntimeLivenessResolver.ts +++ b/src/main/services/team/TeamRuntimeLivenessResolver.ts @@ -46,7 +46,9 @@ const SHELL_COMMAND_NAMES = new Set(['sh', 'bash', 'zsh', 'fish', 'dash', 'login const SECRET_FLAG_PATTERN = /(--(?:api-key|token|password|secret|authorization|auth-token)(?:=|\s+))("[^"]*"|'[^']*'|\S+)/gi; const CLI_ARG_VALUES_CACHE_MAX_COMMANDS = 1_000; +const CLI_ARG_EQUALS_CACHE_MAX_KEYS_PER_COMMAND = 100; const cliArgValuesCache = new Map>(); +const cliArgEqualsCache = new Map>(); function basenameCommand(command: string | undefined): string { const firstToken = command?.trim().split(/\s+/, 1)[0] ?? ''; @@ -108,6 +110,51 @@ function getCachedCliArgValues(command: string, argName: string): readonly strin return values; } +function getCachedCliArgEquals( + command: string, + argName: string, + normalizedExpected: string +): boolean | undefined { + const cachedByKey = cliArgEqualsCache.get(command); + if (!cachedByKey) { + return undefined; + } + const cacheKey = `${argName}\0${normalizedExpected}`; + const cached = cachedByKey.get(cacheKey); + if (cached !== undefined) { + cliArgEqualsCache.delete(command); + cliArgEqualsCache.set(command, cachedByKey); + } + return cached; +} + +function setCachedCliArgEquals( + command: string, + argName: string, + normalizedExpected: string, + value: boolean +): void { + let cachedByKey = cliArgEqualsCache.get(command); + if (!cachedByKey) { + cachedByKey = new Map(); + } + const cacheKey = `${argName}\0${normalizedExpected}`; + if (!cachedByKey.has(cacheKey) && cachedByKey.size >= CLI_ARG_EQUALS_CACHE_MAX_KEYS_PER_COMMAND) { + const oldestKey = cachedByKey.keys().next().value; + if (oldestKey !== undefined) { + cachedByKey.delete(oldestKey); + } + } + cachedByKey.set(cacheKey, value); + cliArgEqualsCache.delete(command); + cliArgEqualsCache.set(command, cachedByKey); + while (cliArgEqualsCache.size > CLI_ARG_VALUES_CACHE_MAX_COMMANDS) { + const oldestCommand = cliArgEqualsCache.keys().next().value; + if (oldestCommand === undefined) break; + cliArgEqualsCache.delete(oldestCommand); + } +} + export function extractCliArgValues(command: string, argName: string): string[] { const values = getCachedCliArgValues(command, argName); return [...values]; @@ -121,7 +168,15 @@ export function commandArgEquals( const normalizedExpected = expected?.trim(); if (!normalizedExpected) return false; if (!command.includes(argName)) return false; - return getCachedCliArgValues(command, argName).some((value) => value === normalizedExpected); + const cached = getCachedCliArgEquals(command, argName, normalizedExpected); + if (cached !== undefined) { + return cached; + } + const value = getCachedCliArgValues(command, argName).some( + (argValue) => argValue === normalizedExpected + ); + setCachedCliArgEquals(command, argName, normalizedExpected, value); + return value; } function collectDescendants( diff --git a/test/main/services/team/TeamRuntimeLivenessResolver.test.ts b/test/main/services/team/TeamRuntimeLivenessResolver.test.ts index 2bb3704f..54d4aa62 100644 --- a/test/main/services/team/TeamRuntimeLivenessResolver.test.ts +++ b/test/main/services/team/TeamRuntimeLivenessResolver.test.ts @@ -1,4 +1,5 @@ import { + commandArgEquals, extractCliArgValues, resolveTeamMemberRuntimeLiveness, sanitizeProcessCommandForDiagnostics, @@ -285,4 +286,13 @@ describe('resolveTeamMemberRuntimeLiveness', () => { it('returns no CLI arg values when the flag is absent', () => { expect(extractCliArgValues('node runtime --other value', '--agent-id')).toEqual([]); }); + + it('matches CLI arg values repeatedly without changing extraction results', () => { + const command = 'node runtime --team-name demo --agent-id "agent alice"'; + + expect(commandArgEquals(command, '--agent-id', 'agent alice')).toBe(true); + expect(commandArgEquals(command, '--agent-id', 'agent-bob')).toBe(false); + expect(commandArgEquals(command, '--agent-id', 'agent alice')).toBe(true); + expect(extractCliArgValues(command, '--agent-id')).toEqual(['agent alice']); + }); });