fix: restore legacy cron schedules and shell diagnostics (#3078)

This commit is contained in:
whyour
2026-09-27 16:16:22 +08:00
parent a67d44cde5
commit a8310e7d51
9 changed files with 108 additions and 18 deletions
+8 -6
View File
@@ -1,6 +1,7 @@
import { ServerUnaryCall, sendUnaryData, status } from '@grpc/grpc-js';
import { AddCronRequest, AddCronResponse } from '../protos/cron';
import nodeSchedule from 'node-schedule';
import CronExpressionParser from 'cron-parser';
import { scheduleStacks } from './data';
import { runCron } from '../shared/runCron';
import Logger from '../loaders/logger';
@@ -17,12 +18,13 @@ const isValidCronField = (cron: string): boolean => {
if (/\s\/\d/.test(cron) || /^\/\d/.test(cron)) {
return false;
}
// 检测 ? 字符:Quartz cron 语法,node-schedule 在大多数位置返回 null
// cron-parser 接受但 node-schedule 拒绝,提前拦截
if (/\?/.test(cron)) {
// 日期和星期字段的 ? 是合法通配符。解析完整表达式,避免将单独的
// ? 等无效规则放行后,在替换恢复快照时清除已有任务。
try {
return CronExpressionParser.parse(cron).hasNext();
} catch {
return false;
}
return true;
};
const addCron = (
@@ -38,7 +40,7 @@ const addCron = (
if (!isValidCronField(schedule)) {
validationErrors.push(
tf(
'任务ID %s: 无效的 cron 表达式 "%s"(不支持裸 /N 步长和 ? 字符)',
'任务ID %s: 无效的 cron 表达式 "%s"',
String(id),
schedule,
),
@@ -50,7 +52,7 @@ const addCron = (
if (!isValidCronField(x.schedule)) {
validationErrors.push(
tf(
'任务ID %s (extra_schedule): 无效的 cron 表达式 "%s"(不支持裸 /N 步长和 ? 字符)',
'任务ID %s (extra_schedule): 无效的 cron 表达式 "%s"',
String(id),
x.schedule,
),
+1 -1
View File
@@ -1102,7 +1102,7 @@ export default class CronService {
await cronClient.addCron(regularCrons, requireScheduler);
} catch (error: any) {
this.logger.warn(
'[crontab] Failed to register cron job in scheduler:',
'[crontab] Failed to register cron job in scheduler: %s',
error?.message || error,
);
if (requireScheduler) throw error;
+4 -4
View File
@@ -142,10 +142,10 @@ const messages: Record<string, Record<string, string>> = {
'Scheduler registration failed, task update rolled back',
'调度器注册失败,任务启用已回滚':
'Scheduler registration failed, task enable rolled back',
'任务ID %s: 无效的 cron 表达式 "%s"(不支持裸 /N 步长和 ? 字符)':
'Task ID %s: invalid cron expression "%s" (bare /N steps and ? character not supported)',
'任务ID %s (extra_schedule): 无效的 cron 表达式 "%s"(不支持裸 /N 步长和 ? 字符)':
'Task ID %s (extra_schedule): invalid cron expression "%s" (bare /N steps and ? character not supported)',
'任务ID %s: 无效的 cron 表达式 "%s"':
'Task ID %s: invalid cron expression "%s"',
'任务ID %s (extra_schedule): 无效的 cron 表达式 "%s"':
'Task ID %s (extra_schedule): invalid cron expression "%s"',
},
};
-5
View File
@@ -17,11 +17,6 @@ const validateSchedule = (value: string, helpers: any) => {
if (/\s\/\d/.test(value) || /^\/\d/.test(value)) {
return helpers.error('any.invalid');
}
// 检测 ? 字符:Quartz cron 语法,node-schedule 在大多数字段上返回 null
if (/\?/.test(value)) {
return helpers.error('any.invalid');
}
try {
if (CronExpressionParser.parse(value).hasNext()) {
return value;