aboutsummaryrefslogtreecommitdiffstats
path: root/services/cron
diff options
context:
space:
mode:
authorChongyi Zheng <harry@harryzheng.com>2023-07-23 23:13:41 -0500
committerGitHub <noreply@github.com>2023-07-24 04:13:41 +0000
commitf2138d6968a96721f58655196ab4f132c20f9425 (patch)
tree810477ea3f83509a0edc40a599ccf1197fb347d3 /services/cron
parentf3d41c61eb0e66aacc269508d27716425673509b (diff)
downloadgitea-f2138d6968a96721f58655196ab4f132c20f9425.tar.gz
gitea-f2138d6968a96721f58655196ab4f132c20f9425.zip
Replace gogs/cron with go-co-op/gocron (#25977)
Replace `github.com/gogs/cron` with `github.com/go-co-op/gocron` as the former package is not maintained for many years. --------- Co-authored-by: delvh <dev.lh@web.de>
Diffstat (limited to 'services/cron')
-rw-r--r--services/cron/cron.go34
-rw-r--r--services/cron/tasks.go22
-rw-r--r--services/cron/tasks_test.go61
3 files changed, 103 insertions, 14 deletions
diff --git a/services/cron/cron.go b/services/cron/cron.go
index 72deb94ceb..e3f31d08f0 100644
--- a/services/cron/cron.go
+++ b/services/cron/cron.go
@@ -14,10 +14,10 @@ import (
"code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/modules/translation"
- "github.com/gogs/cron"
+ "github.com/go-co-op/gocron"
)
-var c = cron.New()
+var scheduler = gocron.NewScheduler(time.Local)
// Prevent duplicate running tasks.
var taskStatusTable = sync.NewStatusTable()
@@ -39,11 +39,11 @@ func NewContext(original context.Context) {
}
}
- c.Start()
+ scheduler.StartAsync()
started = true
lock.Unlock()
graceful.GetManager().RunAtShutdown(context.Background(), func() {
- c.Stop()
+ scheduler.Stop()
lock.Lock()
started = false
lock.Unlock()
@@ -77,13 +77,20 @@ type TaskTable []*TaskTableRow
// ListTasks returns all running cron tasks.
func ListTasks() TaskTable {
- entries := c.Entries()
- eMap := map[string]*cron.Entry{}
- for _, e := range entries {
- eMap[e.Description] = e
+ jobs := scheduler.Jobs()
+ jobMap := map[string]*gocron.Job{}
+ for _, job := range jobs {
+ // the first tag is the task name
+ tags := job.Tags()
+ if len(tags) == 0 { // should never happen
+ continue
+ }
+ jobMap[job.Tags()[0]] = job
}
+
lock.Lock()
defer lock.Unlock()
+
tTable := make([]*TaskTableRow, 0, len(tasks))
for _, task := range tasks {
spec := "-"
@@ -91,10 +98,13 @@ func ListTasks() TaskTable {
next time.Time
prev time.Time
)
- if e, ok := eMap[task.Name]; ok {
- spec = e.Spec
- next = e.Next
- prev = e.Prev
+ if e, ok := jobMap[task.Name]; ok {
+ tags := e.Tags()
+ if len(tags) > 1 {
+ spec = tags[1] // the second tag is the task spec
+ }
+ next = e.NextRun()
+ prev = e.PreviousRun()
}
task.lock.Lock()
tTable = append(tTable, &TaskTableRow{
diff --git a/services/cron/tasks.go b/services/cron/tasks.go
index 1c5493c898..ea1925c26c 100644
--- a/services/cron/tasks.go
+++ b/services/cron/tasks.go
@@ -7,6 +7,7 @@ import (
"context"
"fmt"
"reflect"
+ "strings"
"sync"
"code.gitea.io/gitea/models/db"
@@ -176,8 +177,7 @@ func RegisterTask(name string, config Config, fun func(context.Context, *user_mo
if config.IsEnabled() {
// We cannot use the entry return as there is no way to lock it
- if _, err = c.AddJob(name, config.GetSchedule(), task); err != nil {
- log.Error("Unable to register cron task with name: %s Error: %v", name, err)
+ if err := addTaskToScheduler(task); err != nil {
return err
}
}
@@ -199,3 +199,21 @@ func RegisterTaskFatal(name string, config Config, fun func(context.Context, *us
log.Fatal("Unable to register cron task %s Error: %v", name, err)
}
}
+
+func addTaskToScheduler(task *Task) error {
+ tags := []string{task.Name, task.config.GetSchedule()} // name and schedule can't be get from job, so we add them as tag
+ if scheduleHasSeconds(task.config.GetSchedule()) {
+ scheduler = scheduler.CronWithSeconds(task.config.GetSchedule())
+ } else {
+ scheduler = scheduler.Cron(task.config.GetSchedule())
+ }
+ if _, err := scheduler.Tag(tags...).Do(task.Run); err != nil {
+ log.Error("Unable to register cron task with name: %s Error: %v", task.Name, err)
+ return err
+ }
+ return nil
+}
+
+func scheduleHasSeconds(schedule string) bool {
+ return len(strings.Fields(schedule)) >= 6
+}
diff --git a/services/cron/tasks_test.go b/services/cron/tasks_test.go
new file mode 100644
index 0000000000..69052d739c
--- /dev/null
+++ b/services/cron/tasks_test.go
@@ -0,0 +1,61 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package cron
+
+import (
+ "strconv"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestAddTaskToScheduler(t *testing.T) {
+ assert.Len(t, scheduler.Jobs(), 0)
+ defer scheduler.Clear()
+
+ // no seconds
+ err := addTaskToScheduler(&Task{
+ Name: "task 1",
+ config: &BaseConfig{
+ Schedule: "5 4 * * *",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Len(t, scheduler.Jobs(), 1)
+ assert.Equal(t, "task 1", scheduler.Jobs()[0].Tags()[0])
+ assert.Equal(t, "5 4 * * *", scheduler.Jobs()[0].Tags()[1])
+
+ // with seconds
+ err = addTaskToScheduler(&Task{
+ Name: "task 2",
+ config: &BaseConfig{
+ Schedule: "30 5 4 * * *",
+ },
+ })
+ assert.NoError(t, err)
+ assert.Len(t, scheduler.Jobs(), 2)
+ assert.Equal(t, "task 2", scheduler.Jobs()[1].Tags()[0])
+ assert.Equal(t, "30 5 4 * * *", scheduler.Jobs()[1].Tags()[1])
+}
+
+func TestScheduleHasSeconds(t *testing.T) {
+ tests := []struct {
+ schedule string
+ hasSecond bool
+ }{
+ {"* * * * * *", true},
+ {"* * * * *", false},
+ {"5 4 * * *", false},
+ {"5 4 * * *", false},
+ {"5,8 4 * * *", false},
+ {"* * * * * *", true},
+ {"5,8 4 * * *", false},
+ }
+
+ for i, test := range tests {
+ t.Run(strconv.Itoa(i), func(t *testing.T) {
+ assert.Equal(t, test.hasSecond, scheduleHasSeconds(test.schedule))
+ })
+ }
+}