From c0a437a7937bfdd6a839a3da206b3ee2dad199fc Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 12 Sep 2025 10:52:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20cron=20=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=A8=A1=E6=9D=BF=EF=BC=8C=E6=94=AF=E6=8C=81=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E4=BB=BB=E5=8A=A1=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/new_job.go | 88 ++++++++++++++++++++--------------- templates/jobs/cronjob.go.tpl | 27 +++++++++++ 2 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 templates/jobs/cronjob.go.tpl diff --git a/cmd/new_job.go b/cmd/new_job.go index 6090ec2..7b46785 100644 --- a/cmd/new_job.go +++ b/cmd/new_job.go @@ -2,10 +2,8 @@ package cmd import ( "fmt" - "io/fs" "os" "path/filepath" - "strings" "text/template" "github.com/samber/lo" @@ -23,15 +21,19 @@ func CommandNewJob(root *cobra.Command) { 行为: - 名称转换:输入名的 Snake 与 Pascal 形式分别用于文件名与导出名 -- 输出到 app/jobs/.go +- 输出到 app/jobs/.go;指定 --cron 时输出到 app/jobs/cron_.go - --dry-run 仅打印渲染与写入动作;--dir 指定输出基目录(默认 .) +参数: +- --cron 生成定时任务(渲染 cronjob.go.tpl,输出 cron_.go) + 示例: atomctl new job SendDailyReport`, Args: cobra.ExactArgs(1), RunE: commandNewJobE, } + cmd.Flags().Bool("cron", false, "创建 cron 任务(渲染 cronjob.go.tpl,输出 cron_.go)") root.AddCommand(cmd) } @@ -42,6 +44,7 @@ func commandNewJobE(cmd *cobra.Command, args []string) error { // shared flags dryRun, _ := cmd.Flags().GetBool("dry-run") baseDir, _ := cmd.Flags().GetString("dir") + cron, _ := cmd.Flags().GetBool("cron") basePath := filepath.Join(baseDir, "app/jobs") @@ -64,44 +67,53 @@ func commandNewJobE(cmd *cobra.Command, args []string) error { } } - err = fs.WalkDir(templates.Jobs, "jobs", func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - - if d.IsDir() { - return nil - } - - if strings.HasPrefix(snakeName, "job_") { - snakeName = "job_" + snakeName - } - - filePath := filepath.Join(basePath, snakeName+".go") - tmpl, err := template.ParseFS(templates.Jobs, path) - if err != nil { - return err - } - - if dryRun { - fmt.Printf("[dry-run] render > %s\n", filePath) - return nil - } - - destFile, err := os.Create(filePath) - if err != nil { - return err - } - defer destFile.Close() - - return tmpl.Execute(destFile, map[string]string{ - "Name": camelName, - "ModuleName": gomod.GetModuleName(), - }) - }) + // always render job file + jobOut := filepath.Join(basePath, snakeName+".go") + jobTpl, err := template.ParseFS(templates.Jobs, "jobs/job.go.tpl") if err != nil { return err } + if dryRun { + fmt.Printf("[dry-run] render > %s\n", jobOut) + } else { + fd, err := os.Create(jobOut) + if err != nil { + return err + } + if err := jobTpl.Execute(fd, map[string]string{ + "Name": camelName, + "ModuleName": gomod.GetModuleName(), + }); err != nil { + fd.Close() + return err + } + fd.Close() + } + + // optionally render cron job file when --cron is set + if cron { + cronOut := filepath.Join(basePath, "cron_"+snakeName+".go") + cronTpl, err := template.ParseFS(templates.Jobs, "jobs/cronjob.go.tpl") + if err != nil { + return err + } + if dryRun { + fmt.Printf("[dry-run] render > %s\n", cronOut) + } else { + fd, err := os.Create(cronOut) + if err != nil { + return err + } + if err := cronTpl.Execute(fd, map[string]string{ + "Name": camelName, + "ModuleName": gomod.GetModuleName(), + }); err != nil { + fd.Close() + return err + } + fd.Close() + } + } fmt.Printf("job 已创建: %s\n", snakeName) return nil diff --git a/templates/jobs/cronjob.go.tpl b/templates/jobs/cronjob.go.tpl new file mode 100644 index 0000000..b13e50e --- /dev/null +++ b/templates/jobs/cronjob.go.tpl @@ -0,0 +1,27 @@ +package jobs + +import ( + "context" + "time" + + . "github.com/riverqueue/river" + _ "go.ipao.vip/atom" + "go.ipao.vip/atom/contracts" +) + +var _ contracts.CronJob = (*Cron{{.Name}})(nil) + +// @provider(cronjob) +type Cron{{.Name}} struct{} + +func (c *Cron{{.Name}}) Args() []contracts.CronJobArg { + jobs := []contracts.CronJobArg{ + { + RunOnStart: true, // 启动时运行一次 + PeriodicInterval: cron.Every(time.Hour * 2), // 每2小时运行一次 + // PeriodicInterval: PeriodicInterval("* * * * *"), // 每天凌晨1点运行一次 + Arg: {{.Name}}{}, + }, + } + return jobs +}