mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 21:03:08 +00:00
feat: implement timeout for plan approval and enhance error handling
- Added a 30-minute timeout for user plan approval to prevent indefinite waiting and memory leaks. - Wrapped resolve/reject functions in the waitForPlanApproval method to ensure timeout is cleared upon resolution. - Enhanced error handling in the stream processing loop to ensure proper cleanup and logging of errors. - Improved the handling of task execution and phase completion events for better tracking and user feedback.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -87,17 +87,27 @@ export async function* spawnJSONLProcess(options: SubprocessOptions): AsyncGener
|
|||||||
|
|
||||||
resetTimeout();
|
resetTimeout();
|
||||||
|
|
||||||
// Setup abort handling
|
// Setup abort handling with cleanup
|
||||||
|
let abortHandler: (() => void) | null = null;
|
||||||
if (abortController) {
|
if (abortController) {
|
||||||
abortController.signal.addEventListener('abort', () => {
|
abortHandler = () => {
|
||||||
console.log('[SubprocessManager] Abort signal received, killing process');
|
console.log('[SubprocessManager] Abort signal received, killing process');
|
||||||
if (timeoutHandle) {
|
if (timeoutHandle) {
|
||||||
clearTimeout(timeoutHandle);
|
clearTimeout(timeoutHandle);
|
||||||
}
|
}
|
||||||
childProcess.kill('SIGTERM');
|
childProcess.kill('SIGTERM');
|
||||||
});
|
};
|
||||||
|
abortController.signal.addEventListener('abort', abortHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to clean up abort listener
|
||||||
|
const cleanupAbortListener = () => {
|
||||||
|
if (abortController && abortHandler) {
|
||||||
|
abortController.signal.removeEventListener('abort', abortHandler);
|
||||||
|
abortHandler = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Parse stdout as JSONL (one JSON object per line)
|
// Parse stdout as JSONL (one JSON object per line)
|
||||||
if (childProcess.stdout) {
|
if (childProcess.stdout) {
|
||||||
const rl = readline.createInterface({
|
const rl = readline.createInterface({
|
||||||
@@ -130,7 +140,12 @@ export async function* spawnJSONLProcess(options: SubprocessOptions): AsyncGener
|
|||||||
if (timeoutHandle) {
|
if (timeoutHandle) {
|
||||||
clearTimeout(timeoutHandle);
|
clearTimeout(timeoutHandle);
|
||||||
}
|
}
|
||||||
|
rl.close();
|
||||||
|
cleanupAbortListener();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// No stdout - still need to cleanup abort listener when process exits
|
||||||
|
cleanupAbortListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for process to exit
|
// Wait for process to exit
|
||||||
@@ -195,19 +210,31 @@ export async function spawnProcess(options: SubprocessOptions): Promise<Subproce
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup abort handling
|
// Setup abort handling with cleanup
|
||||||
|
let abortHandler: (() => void) | null = null;
|
||||||
|
const cleanupAbortListener = () => {
|
||||||
|
if (abortController && abortHandler) {
|
||||||
|
abortController.signal.removeEventListener('abort', abortHandler);
|
||||||
|
abortHandler = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (abortController) {
|
if (abortController) {
|
||||||
abortController.signal.addEventListener('abort', () => {
|
abortHandler = () => {
|
||||||
|
cleanupAbortListener();
|
||||||
childProcess.kill('SIGTERM');
|
childProcess.kill('SIGTERM');
|
||||||
reject(new Error('Process aborted'));
|
reject(new Error('Process aborted'));
|
||||||
});
|
};
|
||||||
|
abortController.signal.addEventListener('abort', abortHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
childProcess.on('exit', (code) => {
|
childProcess.on('exit', (code) => {
|
||||||
|
cleanupAbortListener();
|
||||||
resolve({ stdout, stderr, exitCode: code });
|
resolve({ stdout, stderr, exitCode: code });
|
||||||
});
|
});
|
||||||
|
|
||||||
childProcess.on('error', (error) => {
|
childProcess.on('error', (error) => {
|
||||||
|
cleanupAbortListener();
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user