mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-09 05:59:50 +00:00
fix: different cronexpr rules between ui and pocketbase
This commit is contained in:
parent
a74ec95a6a
commit
b8513eb0b6
@ -24,7 +24,7 @@ func (r *WorkflowRepository) ListEnabledAuto(ctx context.Context) ([]*domain.Wor
|
|||||||
"enabled={:enabled} && trigger={:trigger}",
|
"enabled={:enabled} && trigger={:trigger}",
|
||||||
"-created",
|
"-created",
|
||||||
0, 0,
|
0, 0,
|
||||||
dbx.Params{"enabled": true, "trigger": domain.WorkflowTriggerTypeAuto},
|
dbx.Params{"enabled": true, "trigger": string(domain.WorkflowTriggerTypeAuto)},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6,6 +6,6 @@ type certificateService interface {
|
|||||||
InitSchedule(ctx context.Context) error
|
InitSchedule(ctx context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCertificateScheduler(service certificateService) error {
|
func InitCertificateScheduler(service certificateService) error {
|
||||||
return service.InitSchedule(context.Background())
|
return service.InitSchedule(context.Background())
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package scheduler
|
package scheduler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/usual2970/certimate/internal/app"
|
||||||
"github.com/usual2970/certimate/internal/certificate"
|
"github.com/usual2970/certimate/internal/certificate"
|
||||||
"github.com/usual2970/certimate/internal/repository"
|
"github.com/usual2970/certimate/internal/repository"
|
||||||
"github.com/usual2970/certimate/internal/workflow"
|
"github.com/usual2970/certimate/internal/workflow"
|
||||||
@ -14,7 +15,11 @@ func Register() {
|
|||||||
certificateRepo := repository.NewCertificateRepository()
|
certificateRepo := repository.NewCertificateRepository()
|
||||||
certificateSvc := certificate.NewCertificateService(certificateRepo)
|
certificateSvc := certificate.NewCertificateService(certificateRepo)
|
||||||
|
|
||||||
NewCertificateScheduler(certificateSvc)
|
if err := InitWorkflowScheduler(workflowSvc); err != nil {
|
||||||
|
app.GetLogger().Error("failed to init workflow scheduler", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
NewWorkflowScheduler(workflowSvc)
|
if err := InitCertificateScheduler(certificateSvc); err != nil {
|
||||||
|
app.GetLogger().Error("failed to init certificate scheduler", "err", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@ type workflowService interface {
|
|||||||
InitSchedule(ctx context.Context) error
|
InitSchedule(ctx context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorkflowScheduler(service workflowService) error {
|
func InitWorkflowScheduler(service workflowService) error {
|
||||||
return service.InitSchedule(context.Background())
|
return service.InitSchedule(context.Background())
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ func (w *WorkflowDispatcher) Dispatch(data *WorkflowWorkerData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.enqueueWorker(data)
|
w.enqueueWorker(data)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case w.chWork <- data:
|
case w.chWork <- data:
|
||||||
default:
|
default:
|
||||||
@ -138,6 +139,11 @@ func (w *WorkflowDispatcher) Shutdown() {
|
|||||||
w.queueMutex.Unlock()
|
w.queueMutex.Unlock()
|
||||||
|
|
||||||
// 等待所有正在执行的 WorkflowRun 完成
|
// 等待所有正在执行的 WorkflowRun 完成
|
||||||
|
w.workerMutex.Lock()
|
||||||
|
for _, worker := range w.workers {
|
||||||
|
worker.Cancel()
|
||||||
|
}
|
||||||
|
w.workerMutex.Unlock()
|
||||||
w.wg.Wait()
|
w.wg.Wait()
|
||||||
w.workers = make(map[string]*workflowWorker)
|
w.workers = make(map[string]*workflowWorker)
|
||||||
w.workerIdMap = make(map[string]string)
|
w.workerIdMap = make(map[string]string)
|
||||||
|
@ -72,7 +72,6 @@ func onWorkflowRecordCreateOrUpdate(ctx context.Context, record *core.Record) er
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.GetLogger().Error("add cron job failed", "err", err)
|
|
||||||
return fmt.Errorf("add cron job failed: %w", err)
|
return fmt.Errorf("add cron job failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error {
|
|||||||
|
|
||||||
scheduler := app.GetScheduler()
|
scheduler := app.GetScheduler()
|
||||||
for _, workflow := range workflows {
|
for _, workflow := range workflows {
|
||||||
|
var errs []error
|
||||||
|
|
||||||
err := scheduler.Add(fmt.Sprintf("workflow#%s", workflow.Id), workflow.TriggerCron, func() {
|
err := scheduler.Add(fmt.Sprintf("workflow#%s", workflow.Id), workflow.TriggerCron, func() {
|
||||||
s.StartRun(ctx, &dtos.WorkflowStartRunReq{
|
s.StartRun(ctx, &dtos.WorkflowStartRunReq{
|
||||||
WorkflowId: workflow.Id,
|
WorkflowId: workflow.Id,
|
||||||
@ -55,7 +57,11 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"workflow_node.start.form.trigger_cron.label": "Cron expression",
|
"workflow_node.start.form.trigger_cron.label": "Cron expression",
|
||||||
"workflow_node.start.form.trigger_cron.placeholder": "Please enter cron expression",
|
"workflow_node.start.form.trigger_cron.placeholder": "Please enter cron expression",
|
||||||
"workflow_node.start.form.trigger_cron.errmsg.invalid": "Please enter a valid cron expression",
|
"workflow_node.start.form.trigger_cron.errmsg.invalid": "Please enter a valid cron expression",
|
||||||
"workflow_node.start.form.trigger_cron.tooltip": "Time zone is based on the server.",
|
"workflow_node.start.form.trigger_cron.tooltip": "Exactly 5 space separated segments. Time zone is based on the server.",
|
||||||
"workflow_node.start.form.trigger_cron.extra": "Expected execution time for the last 5 times:",
|
"workflow_node.start.form.trigger_cron.extra": "Expected execution time for the last 5 times:",
|
||||||
"workflow_node.start.form.trigger_cron.guide": "Tips: If you have multiple workflows, it is recommended to set them to run at multiple times of the day instead of always running at specific times.<br><br>Reference links:<br>1. <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt rate limits</a><br>2. <a href=\"https://letsencrypt.org/docs/faq/#why-should-my-let-s-encrypt-acme-client-run-at-a-random-time\" target=\"_blank\">Why should my Let’s Encrypt (ACME) client run at a random time?</a>",
|
"workflow_node.start.form.trigger_cron.guide": "Tips: If you have multiple workflows, it is recommended to set them to run at multiple times of the day instead of always running at specific times.<br><br>Reference links:<br>1. <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt rate limits</a><br>2. <a href=\"https://letsencrypt.org/docs/faq/#why-should-my-let-s-encrypt-acme-client-run-at-a-random-time\" target=\"_blank\">Why should my Let’s Encrypt (ACME) client run at a random time?</a>",
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"workflow_node.start.form.trigger_cron.label": "Cron 表达式",
|
"workflow_node.start.form.trigger_cron.label": "Cron 表达式",
|
||||||
"workflow_node.start.form.trigger_cron.placeholder": "请输入 Cron 表达式",
|
"workflow_node.start.form.trigger_cron.placeholder": "请输入 Cron 表达式",
|
||||||
"workflow_node.start.form.trigger_cron.errmsg.invalid": "请输入正确的 Cron 表达式",
|
"workflow_node.start.form.trigger_cron.errmsg.invalid": "请输入正确的 Cron 表达式",
|
||||||
"workflow_node.start.form.trigger_cron.tooltip": "支持使用任意值(即 <strong>*</strong>)、值列表分隔符(即 <strong>,</strong>)、值的范围(即 <strong>-</strong>)、步骤值(即 <strong>/</strong>)等四种表达式,时区以服务器设置为准。",
|
"workflow_node.start.form.trigger_cron.tooltip": "五段式表达式,支持使用任意值(即 <strong>*</strong>)、值列表分隔符(即 <strong>,</strong>)、值的范围(即 <strong>-</strong>)、步骤值(即 <strong>/</strong>)等四种表达式。时区以服务器设置为准。",
|
||||||
"workflow_node.start.form.trigger_cron.extra": "预计最近 5 次执行时间:",
|
"workflow_node.start.form.trigger_cron.extra": "预计最近 5 次执行时间:",
|
||||||
"workflow_node.start.form.trigger_cron.guide": "小贴士:如果你有多个工作流,建议将它们设置为在一天中的多个时间段运行,而非总是在相同的特定时间。<br><br>参考链接:<br>1. <a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt 速率限制</a><br>2. <a href=\"https://letsencrypt.org/zh-cn/docs/faq/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-let-s-encrypt-acme-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%97%B6%E9%97%B4%E5%BA%94%E5%BD%93%E9%9A%8F%E6%9C%BA\" target=\"_blank\">为什么我的 Let’s Encrypt (ACME) 客户端启动时间应当随机?</a>",
|
"workflow_node.start.form.trigger_cron.guide": "小贴士:如果你有多个工作流,建议将它们设置为在一天中的多个时间段运行,而非总是在相同的特定时间。<br><br>参考链接:<br>1. <a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt 速率限制</a><br>2. <a href=\"https://letsencrypt.org/zh-cn/docs/faq/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-let-s-encrypt-acme-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%97%B6%E9%97%B4%E5%BA%94%E5%BD%93%E9%9A%8F%E6%9C%BA\" target=\"_blank\">为什么我的 Let’s Encrypt (ACME) 客户端启动时间应当随机?</a>",
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
export const validCronExpression = (expr: string): boolean => {
|
export const validCronExpression = (expr: string): boolean => {
|
||||||
try {
|
try {
|
||||||
parseExpression(expr);
|
parseExpression(expr);
|
||||||
|
|
||||||
|
if (expr.trim().split(" ").length !== 5) return false; // pocketbase 后端仅支持五段式的表达式
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
@ -10,9 +12,8 @@ export const validCronExpression = (expr: string): boolean => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getNextCronExecutions = (expr: string, times = 1): Date[] => {
|
export const getNextCronExecutions = (expr: string, times = 1): Date[] => {
|
||||||
if (!expr) return [];
|
if (!validCronExpression(expr)) return [];
|
||||||
|
|
||||||
try {
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const cron = parseExpression(expr, { currentDate: now, iterator: true });
|
const cron = parseExpression(expr, { currentDate: now, iterator: true });
|
||||||
|
|
||||||
@ -22,7 +23,4 @@ export const getNextCronExecutions = (expr: string, times = 1): Date[] => {
|
|||||||
result.push(next.value.toDate());
|
result.push(next.value.toDate());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user