perf(comment-checker): add hard process reap and global semaphore to prevent CPU runaway

This commit is contained in:
YeonGyu-Kim
2026-02-13 11:49:29 +09:00
parent 4c10723b33
commit f6fbac458e
3 changed files with 264 additions and 93 deletions
+62 -40
View File
@@ -4,6 +4,24 @@ import { existsSync } from "fs"
import { runCommentChecker, getCommentCheckerPath, startBackgroundInit, type HookInput } from "./cli"
let cliPathPromise: Promise<string | null> | null = null
let isRunning = false
async function withCommentCheckerLock<T>(
fn: () => Promise<T>,
fallback: T,
debugLog: (...args: unknown[]) => void,
): Promise<T> {
if (isRunning) {
debugLog("comment-checker already running, skipping")
return fallback
}
isRunning = true
try {
return await fn()
} finally {
isRunning = false
}
}
export function initializeCommentCheckerCli(debugLog: (...args: unknown[]) => void): void {
// Start background CLI initialization (may trigger lazy download)
@@ -30,32 +48,34 @@ export async function processWithCli(
customPrompt: string | undefined,
debugLog: (...args: unknown[]) => void,
): Promise<void> {
void input
debugLog("using CLI mode with path:", cliPath)
await withCommentCheckerLock(async () => {
void input
debugLog("using CLI mode with path:", cliPath)
const hookInput: HookInput = {
session_id: pendingCall.sessionID,
tool_name: pendingCall.tool.charAt(0).toUpperCase() + pendingCall.tool.slice(1),
transcript_path: "",
cwd: process.cwd(),
hook_event_name: "PostToolUse",
tool_input: {
file_path: pendingCall.filePath,
content: pendingCall.content,
old_string: pendingCall.oldString,
new_string: pendingCall.newString,
edits: pendingCall.edits,
},
}
const hookInput: HookInput = {
session_id: pendingCall.sessionID,
tool_name: pendingCall.tool.charAt(0).toUpperCase() + pendingCall.tool.slice(1),
transcript_path: "",
cwd: process.cwd(),
hook_event_name: "PostToolUse",
tool_input: {
file_path: pendingCall.filePath,
content: pendingCall.content,
old_string: pendingCall.oldString,
new_string: pendingCall.newString,
edits: pendingCall.edits,
},
}
const result = await runCommentChecker(hookInput, cliPath, customPrompt)
const result = await runCommentChecker(hookInput, cliPath, customPrompt)
if (result.hasComments && result.message) {
debugLog("CLI detected comments, appending message")
output.output += `\n\n${result.message}`
} else {
debugLog("CLI: no comments detected")
}
if (result.hasComments && result.message) {
debugLog("CLI detected comments, appending message")
output.output += `\n\n${result.message}`
} else {
debugLog("CLI: no comments detected")
}
}, undefined, debugLog)
}
export interface ApplyPatchEdit {
@@ -75,25 +95,27 @@ export async function processApplyPatchEditsWithCli(
debugLog("processing apply_patch edits:", edits.length)
for (const edit of edits) {
const hookInput: HookInput = {
session_id: sessionID,
tool_name: "Edit",
transcript_path: "",
cwd: process.cwd(),
hook_event_name: "PostToolUse",
tool_input: {
file_path: edit.filePath,
old_string: edit.before,
new_string: edit.after,
},
}
await withCommentCheckerLock(async () => {
const hookInput: HookInput = {
session_id: sessionID,
tool_name: "Edit",
transcript_path: "",
cwd: process.cwd(),
hook_event_name: "PostToolUse",
tool_input: {
file_path: edit.filePath,
old_string: edit.before,
new_string: edit.after,
},
}
const result = await runCommentChecker(hookInput, cliPath, customPrompt)
const result = await runCommentChecker(hookInput, cliPath, customPrompt)
if (result.hasComments && result.message) {
debugLog("CLI detected comments for apply_patch file:", edit.filePath)
output.output += `\n\n${result.message}`
}
if (result.hasComments && result.message) {
debugLog("CLI detected comments for apply_patch file:", edit.filePath)
output.output += `\n\n${result.message}`
}
}, undefined, debugLog)
}
}