feat: 加固运行期可靠性并补齐调度与观测接口

- 运行句柄按 run_id 归属,修复取消后重跑时闸门被旧运行删除的竞态
- 调度循环改用取消令牌退出,启动时对账遗留运行,校验 rows_affected
- 三类任务统一参与调度,新增 /api/v1/stats 与 /api/v1/schedule
- SQLite 启用 WAL 与 busy_timeout,日志清理跳过活跃文件,单行上限 256 KiB
- 前端缓存管理令牌并在 403 时重试一次,仪表盘改用统计接口
This commit is contained in:
2026-10-26 00:38:16 +08:00
parent 773196d689
commit 815258c19b
19 changed files with 990 additions and 93 deletions
+114
View File
@@ -132,6 +132,22 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/v1/schedule": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["list_schedule"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/session": {
parameters: {
query?: never;
@@ -148,6 +164,22 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/v1/stats": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["task_stats"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/system/directories": {
parameters: {
query?: never;
@@ -338,6 +370,15 @@ export interface components {
RunStatus: "queued" | "running" | "succeeded" | "failed" | "timed_out" | "cancelled" | "skipped";
/** @enum {string} */
RunTrigger: "schedule" | "manual" | "retry";
/** @description 已注册调度的任务及其下次触发时间。 */
ScheduledTaskResponse: {
/**
* Format: date-time
* @description 下次触发时间;调度正在重建时可能为空
*/
next_run_at?: string | null;
task_id: string;
};
SessionResponse: {
/** @description Random per-process token required for mutating browser requests. */
token: string;
@@ -427,6 +468,39 @@ export interface components {
task_id: string;
trigger: components["schemas"]["RunTrigger"];
};
/** @description 仪表盘指标:一次请求拿到全部计数,避免为每个指标各发一次列表查询。 */
TaskStatsResponse: {
/**
* Format: int64
* @description 已启用任务数
*/
enabled: number;
/**
* Format: int64
* @description HTTP 类任务数
*/
http: number;
/**
* Format: int64
* @description 进程类任务数
*/
process: number;
/**
* Format: int64
* @description 当前正在执行的任务数
*/
running: number;
/**
* Format: int64
* @description 脚本类任务数
*/
script: number;
/**
* Format: int64
* @description 任务总数
*/
total: number;
};
UpdateTaskRequest: {
action: components["schemas"]["TaskAction"];
concurrency_policy?: components["schemas"]["ConcurrencyPolicy"];
@@ -718,6 +792,26 @@ export interface operations {
};
};
};
list_schedule: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Next trigger time per enabled task */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ScheduledTaskResponse"][];
};
};
};
};
session: {
parameters: {
query?: never;
@@ -738,6 +832,26 @@ export interface operations {
};
};
};
task_stats: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Dashboard counters */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["TaskStatsResponse"];
};
};
};
};
list_directories: {
parameters: {
query?: {