From 5fe754216033bad2b304a115f6c154e787c57ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 8 Apr 2026 20:09:32 +0800 Subject: [PATCH] fix: prevent duplicate concurrent executions of the same scheduled task executeTask() lacked a runningTasks guard, so manual "Run Now" or server restarts could spawn a second subprocess while one was already running. Now checks runningTasks at entry and skips if already in flight. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/server/services/cronScheduler.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/server/services/cronScheduler.ts b/src/server/services/cronScheduler.ts index f09272f1..03d8bf29 100644 --- a/src/server/services/cronScheduler.ts +++ b/src/server/services/cronScheduler.ts @@ -314,6 +314,22 @@ export class CronScheduler { * @param options.createSession When true, creates a Session for rich output viewing (used for manual "Run Now") */ async executeTask(task: CronTask, options?: { createSession?: boolean }): Promise { + // Prevent concurrent executions of the same task + const existing = this.runningTasks.get(task.id) + if (existing) { + console.log( + `[CronScheduler] Task ${task.id} is already running (runId=${existing.runId}), skipping`, + ) + return { + id: existing.runId, + taskId: task.id, + taskName: task.name || task.prompt.slice(0, 60), + startedAt: new Date(existing.startedAt).toISOString(), + status: 'running', + prompt: task.prompt, + } + } + const runId = crypto.randomBytes(6).toString('hex') const startedAt = new Date().toISOString() const workDir = task.folderPath || os.homedir()