From d64dc64df717f25fd0a76c9d5d64dc4c6d732e32 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:37:15 +0000 Subject: [PATCH 1/6] Initial plan From f043aa62e4d39f28c31a4c29dbc5f5921d92b34e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:42:44 +0000 Subject: [PATCH 2/6] Fix task status reset issue - preserve running tasks on restart Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --- back/config/util.ts | 10 ++++++++++ back/loaders/initData.ts | 17 +++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/back/config/util.ts b/back/config/util.ts index 7d61f74f..e80ab284 100644 --- a/back/config/util.ts +++ b/back/config/util.ts @@ -397,6 +397,16 @@ export function psTree(pid: number): Promise { }); } +export function isPidRunning(pid: number): boolean { + try { + // Signal 0 doesn't kill the process, just checks if it exists + process.kill(pid, 0); + return true; + } catch (error) { + return false; + } +} + export async function killTask(pid: number) { const pids = await psTree(pid); diff --git a/back/loaders/initData.ts b/back/loaders/initData.ts index f8b5315a..06968765 100644 --- a/back/loaders/initData.ts +++ b/back/loaders/initData.ts @@ -13,7 +13,7 @@ import { AuthDataType, SystemModel } from '../data/system'; import SystemService from '../services/system'; import UserService from '../services/user'; import { writeFile, readFile } from 'fs/promises'; -import { createRandomString, fileExist, safeJSONParse } from '../config/util'; +import { createRandomString, fileExist, safeJSONParse, isPidRunning } from '../config/util'; import OpenService from '../services/open'; import { shareStore } from '../shared/store'; import Logger from './logger'; @@ -132,7 +132,20 @@ export default async () => { }); // 初始化更新所有任务状态为空闲 - await CrontabModel.update({ status: CrontabStatus.idle }, { where: {} }); + // 但保留仍在运行的任务的状态 + const allCrons = await CrontabModel.findAll({ raw: true }); + for (const cron of allCrons) { + // 如果任务有 PID 且进程仍在运行,则保持其状态 + if (cron.pid && isPidRunning(cron.pid)) { + // 保留当前状态(running 或 queued) + continue; + } + // 否则将状态重置为 idle,并清除 PID + await CrontabModel.update( + { status: CrontabStatus.idle, pid: undefined }, + { where: { id: cron.id } } + ); + } // 初始化时执行一次所有的 ql repo 任务 CrontabModel.findAll({ From 1124040eebafac730db653010a57f858bd3f9107 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:46:15 +0000 Subject: [PATCH 3/6] Optimize PID validation and use bulk database update Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --- back/config/util.ts | 5 +++++ back/loaders/initData.ts | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/back/config/util.ts b/back/config/util.ts index e80ab284..47b7b183 100644 --- a/back/config/util.ts +++ b/back/config/util.ts @@ -398,6 +398,11 @@ export function psTree(pid: number): Promise { } export function isPidRunning(pid: number): boolean { + // Validate PID is a positive integer + if (!pid || pid <= 0 || !Number.isInteger(pid)) { + return false; + } + try { // Signal 0 doesn't kill the process, just checks if it exists process.kill(pid, 0); diff --git a/back/loaders/initData.ts b/back/loaders/initData.ts index 06968765..8fbe3b08 100644 --- a/back/loaders/initData.ts +++ b/back/loaders/initData.ts @@ -134,16 +134,23 @@ export default async () => { // 初始化更新所有任务状态为空闲 // 但保留仍在运行的任务的状态 const allCrons = await CrontabModel.findAll({ raw: true }); + const idsToReset: number[] = []; + for (const cron of allCrons) { // 如果任务有 PID 且进程仍在运行,则保持其状态 if (cron.pid && isPidRunning(cron.pid)) { // 保留当前状态(running 或 queued) continue; } - // 否则将状态重置为 idle,并清除 PID + // 收集需要重置的任务 ID + idsToReset.push(cron.id!); + } + + // 批量更新所有需要重置的任务 + if (idsToReset.length > 0) { await CrontabModel.update( { status: CrontabStatus.idle, pid: undefined }, - { where: { id: cron.id } } + { where: { id: { [Op.in]: idsToReset } } } ); } From a56f2393a48e3a3b8fd568bbb215eae972257d6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:48:11 +0000 Subject: [PATCH 4/6] Address code review feedback - improve null checks Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --- back/config/util.ts | 4 ++-- back/loaders/initData.ts | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/back/config/util.ts b/back/config/util.ts index 47b7b183..e4a7ce69 100644 --- a/back/config/util.ts +++ b/back/config/util.ts @@ -398,8 +398,8 @@ export function psTree(pid: number): Promise { } export function isPidRunning(pid: number): boolean { - // Validate PID is a positive integer - if (!pid || pid <= 0 || !Number.isInteger(pid)) { + // Validate PID: must be a positive integer + if (pid == null || pid <= 0 || !Number.isInteger(pid)) { return false; } diff --git a/back/loaders/initData.ts b/back/loaders/initData.ts index 8fbe3b08..c9d87c74 100644 --- a/back/loaders/initData.ts +++ b/back/loaders/initData.ts @@ -143,7 +143,9 @@ export default async () => { continue; } // 收集需要重置的任务 ID - idsToReset.push(cron.id!); + if (cron.id) { + idsToReset.push(cron.id); + } } // 批量更新所有需要重置的任务 From 8ae7a85bf8191acd44f31769ab9bbe01a2892b8a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:50:12 +0000 Subject: [PATCH 5/6] Use consistent null checking pattern for PID validation Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --- back/loaders/initData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/loaders/initData.ts b/back/loaders/initData.ts index c9d87c74..b3407eb6 100644 --- a/back/loaders/initData.ts +++ b/back/loaders/initData.ts @@ -138,7 +138,7 @@ export default async () => { for (const cron of allCrons) { // 如果任务有 PID 且进程仍在运行,则保持其状态 - if (cron.pid && isPidRunning(cron.pid)) { + if (cron.pid != null && isPidRunning(cron.pid)) { // 保留当前状态(running 或 queued) continue; } From c32a53c40b9a8d3f543c4b1351e09185f9c53e0b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:51:31 +0000 Subject: [PATCH 6/6] Optimize memory usage by fetching only required fields Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --- back/loaders/initData.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/back/loaders/initData.ts b/back/loaders/initData.ts index b3407eb6..9e90daf0 100644 --- a/back/loaders/initData.ts +++ b/back/loaders/initData.ts @@ -133,7 +133,10 @@ export default async () => { // 初始化更新所有任务状态为空闲 // 但保留仍在运行的任务的状态 - const allCrons = await CrontabModel.findAll({ raw: true }); + const allCrons = await CrontabModel.findAll({ + attributes: ['id', 'pid'], + raw: true, + }); const idsToReset: number[] = []; for (const cron of allCrons) {