fix(cron): prevent concurrent cron execution and queue properly

- Add queue-based cron processing in nonInteractiveCli for sequential execution
- Block cron processing while user prompt is active in Session
- Drain cron queue after prompt completion to process queued jobs
- Reduce recurring task auto-expiry from 7 days to 3 days

This fixes race conditions where cron jobs could fire during active prompts
and ensures cron prompts are processed sequentially.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
tanzhenxin 2026-03-30 19:49:17 +08:00
parent dbc86e7672
commit 05f38543cf
6 changed files with 32 additions and 15 deletions

View file

@ -379,20 +379,25 @@ export async function runNonInteractive(
// Start the scheduler and wait for all jobs to complete or be deleted.
// Each fired prompt is processed as a new turn through the same loop.
await new Promise<void>((resolve) => {
const cronQueue: string[] = [];
let processing = false;
const checkDone = () => {
if (scheduler.size === 0) {
if (scheduler.size === 0 && !processing) {
scheduler.stop();
resolve();
}
};
scheduler.start((job: { prompt: string }) => {
// Process fired prompt as a new turn
(async () => {
try {
const drainQueue = async () => {
if (processing) return;
processing = true;
try {
while (cronQueue.length > 0) {
const cronPrompt = cronQueue.shift()!;
turnCount++;
let cronMessages: Content[] = [
{ role: 'user', parts: [{ text: job.prompt }] },
{ role: 'user', parts: [{ text: cronPrompt }] },
];
let cronIsFirstTurn = true;
@ -476,16 +481,21 @@ export async function runNonInteractive(
{ role: 'user', parts: cronToolResponseParts },
];
} else {
// Cron turn done — check if we should exit
checkDone();
break;
}
}
} catch (error) {
debugLogger.error('Error processing cron prompt:', error);
checkDone();
}
})();
} catch (error) {
debugLogger.error('Error processing cron prompt:', error);
} finally {
processing = false;
checkDone();
}
};
scheduler.start((job: { prompt: string }) => {
cronQueue.push(job.prompt);
void drainQueue();
});
// Also check immediately in case jobs were already deleted