fix: increase timeouts for slow systems

Phase 2 of worker lifecycle fix - applying timeout increases:

- hook-constants.ts: DEFAULT 120s→300s, HEALTH_CHECK 1s→30s, RETRIES 15→300
- worker-service.ts: context init 30s→300s, MCP 15s→300s, PowerShell 5s→60s
- BranchManager.ts: GIT_COMMAND 30s→300s, NPM_INSTALL 120s→600s
- hooks.json: worker start/restart 30s→180s, hook execution 120s→300s

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2025-12-26 18:55:40 -05:00
parent 3f8beaa10d
commit 8326fa59df
4 changed files with 21 additions and 21 deletions
+7 -7
View File
@@ -8,7 +8,7 @@
{ {
"type": "command", "type": "command",
"command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" restart", "command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" restart",
"timeout": 30 "timeout": 180
}, },
{ {
"type": "command", "type": "command",
@@ -29,12 +29,12 @@
{ {
"type": "command", "type": "command",
"command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" start", "command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" start",
"timeout": 30 "timeout": 180
}, },
{ {
"type": "command", "type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js\"", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/new-hook.js\"",
"timeout": 120 "timeout": 300
} }
] ]
} }
@@ -46,12 +46,12 @@
{ {
"type": "command", "type": "command",
"command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" start", "command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" start",
"timeout": 30 "timeout": 180
}, },
{ {
"type": "command", "type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js\"", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/save-hook.js\"",
"timeout": 120 "timeout": 300
} }
] ]
} }
@@ -62,12 +62,12 @@
{ {
"type": "command", "type": "command",
"command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" start", "command": "bun \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-cli.js\" start",
"timeout": 30 "timeout": 180
}, },
{ {
"type": "command", "type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js\"", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/summary-hook.js\"",
"timeout": 120 "timeout": 300
} }
] ]
} }
+8 -8
View File
@@ -266,7 +266,7 @@ export class WorkerService {
this.app.get('/api/context/inject', async (req, res, next) => { this.app.get('/api/context/inject', async (req, res, next) => {
try { try {
// Wait for initialization to complete (with timeout) // Wait for initialization to complete (with timeout)
const timeoutMs = 30000; // 30 second timeout const timeoutMs = 300000; // 5 minute timeout for slow systems
const timeoutPromise = new Promise((_, reject) => const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Initialization timeout')), timeoutMs) setTimeout(() => reject(new Error('Initialization timeout')), timeoutMs)
); );
@@ -326,7 +326,7 @@ export class WorkerService {
if (isWindows) { if (isWindows) {
// Windows: Use PowerShell Get-CimInstance to find chroma-mcp processes // Windows: Use PowerShell Get-CimInstance to find chroma-mcp processes
const cmd = `powershell -Command "Get-CimInstance Win32_Process | Where-Object { $_.Name -like '*python*' -and $_.CommandLine -like '*chroma-mcp*' } | Select-Object -ExpandProperty ProcessId"`; const cmd = `powershell -Command "Get-CimInstance Win32_Process | Where-Object { $_.Name -like '*python*' -and $_.CommandLine -like '*chroma-mcp*' } | Select-Object -ExpandProperty ProcessId"`;
const { stdout } = await execAsync(cmd, { timeout: 5000 }); const { stdout } = await execAsync(cmd, { timeout: 60000 });
if (!stdout.trim()) { if (!stdout.trim()) {
logger.debug('SYSTEM', 'No orphaned chroma-mcp processes found (Windows)'); logger.debug('SYSTEM', 'No orphaned chroma-mcp processes found (Windows)');
@@ -381,7 +381,7 @@ export class WorkerService {
logger.warn('SYSTEM', 'Skipping invalid PID', { pid }); logger.warn('SYSTEM', 'Skipping invalid PID', { pid });
continue; continue;
} }
execSync(`taskkill /PID ${pid} /T /F`, { timeout: 5000, stdio: 'ignore' }); execSync(`taskkill /PID ${pid} /T /F`, { timeout: 60000, stdio: 'ignore' });
} }
} else { } else {
await execAsync(`kill ${pids.join(' ')}`); await execAsync(`kill ${pids.join(' ')}`);
@@ -463,11 +463,11 @@ export class WorkerService {
env: process.env env: process.env
}); });
// Add timeout guard to prevent hanging on MCP connection (15 seconds) // Add timeout guard to prevent hanging on MCP connection (5 minutes for slow systems)
const MCP_INIT_TIMEOUT_MS = 15000; const MCP_INIT_TIMEOUT_MS = 300000;
const mcpConnectionPromise = this.mcpClient.connect(transport); const mcpConnectionPromise = this.mcpClient.connect(transport);
const timeoutPromise = new Promise<never>((_, reject) => const timeoutPromise = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('MCP connection timeout after 15s')), MCP_INIT_TIMEOUT_MS) setTimeout(() => reject(new Error('MCP connection timeout after 5 minutes')), MCP_INIT_TIMEOUT_MS)
); );
await Promise.race([mcpConnectionPromise, timeoutPromise]); await Promise.race([mcpConnectionPromise, timeoutPromise]);
@@ -652,7 +652,7 @@ export class WorkerService {
} }
const cmd = `powershell -Command "Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq ${parentPid} } | Select-Object -ExpandProperty ProcessId"`; const cmd = `powershell -Command "Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq ${parentPid} } | Select-Object -ExpandProperty ProcessId"`;
const { stdout } = await execAsync(cmd, { timeout: 5000 }); const { stdout } = await execAsync(cmd, { timeout: 60000 });
return stdout return stdout
.trim() .trim()
.split('\n') .split('\n')
@@ -672,7 +672,7 @@ export class WorkerService {
if (process.platform === 'win32') { if (process.platform === 'win32') {
// /T kills entire process tree, /F forces termination // /T kills entire process tree, /F forces termination
await execAsync(`taskkill /PID ${pid} /T /F`, { timeout: 5000 }); await execAsync(`taskkill /PID ${pid} /T /F`, { timeout: 60000 });
logger.info('SYSTEM', 'Killed process', { pid }); logger.info('SYSTEM', 'Killed process', { pid });
} else { } else {
process.kill(pid, 'SIGKILL'); process.kill(pid, 'SIGKILL');
+3 -3
View File
@@ -28,9 +28,9 @@ function isValidBranchName(branchName: string): boolean {
return validBranchRegex.test(branchName) && !branchName.includes('..'); return validBranchRegex.test(branchName) && !branchName.includes('..');
} }
// Timeout constants // Timeout constants (increased for slow systems)
const GIT_COMMAND_TIMEOUT_MS = 30_000; const GIT_COMMAND_TIMEOUT_MS = 300_000;
const NPM_INSTALL_TIMEOUT_MS = 120_000; const NPM_INSTALL_TIMEOUT_MS = 600_000;
const DEFAULT_SHELL_TIMEOUT_MS = 60_000; const DEFAULT_SHELL_TIMEOUT_MS = 60_000;
export interface BranchInfo { export interface BranchInfo {
+3 -3
View File
@@ -1,8 +1,8 @@
export const HOOK_TIMEOUTS = { export const HOOK_TIMEOUTS = {
DEFAULT: 120000, // Standard HTTP timeout (up from 2000ms) DEFAULT: 300000, // Standard HTTP timeout (5 min for slow systems)
HEALTH_CHECK: 1000, // Worker health check (up from 500ms) HEALTH_CHECK: 30000, // Worker health check (30s for slow systems)
WORKER_STARTUP_WAIT: 1000, WORKER_STARTUP_WAIT: 1000,
WORKER_STARTUP_RETRIES: 15, WORKER_STARTUP_RETRIES: 300,
PRE_RESTART_SETTLE_DELAY: 2000, // Give files time to sync before restart PRE_RESTART_SETTLE_DELAY: 2000, // Give files time to sync before restart
WINDOWS_MULTIPLIER: 1.5 // Platform-specific adjustment WINDOWS_MULTIPLIER: 1.5 // Platform-specific adjustment
} as const; } as const;