1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cron
import (
"context"
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/migrations"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/sync"
mirror_service "code.gitea.io/gitea/services/mirror"
"github.com/gogs/cron"
)
const (
mirrorUpdate = "mirror_update"
gitFsck = "git_fsck"
checkRepos = "check_repos"
archiveCleanup = "archive_cleanup"
syncExternalUsers = "sync_external_users"
deletedBranchesCleanup = "deleted_branches_cleanup"
updateMigrationPosterID = "update_migration_post_id"
)
var c = cron.New()
// Prevent duplicate running tasks.
var taskStatusTable = sync.NewStatusTable()
// Func defines a cron function body
type Func func()
// WithUnique wrap a cron func with an unique running check
func WithUnique(name string, body func(context.Context)) Func {
return func() {
if !taskStatusTable.StartIfNotRunning(name) {
return
}
defer taskStatusTable.Stop(name)
graceful.GetManager().RunWithShutdownContext(body)
}
}
// NewContext begins cron tasks
// Each cron task is run within the shutdown context as a running server
// AtShutdown the cron server is stopped
func NewContext() {
var (
entry *cron.Entry
err error
)
if setting.Cron.UpdateMirror.Enabled {
entry, err = c.AddFunc("Update mirrors", setting.Cron.UpdateMirror.Schedule, WithUnique(mirrorUpdate, mirror_service.Update))
if err != nil {
log.Fatal("Cron[Update mirrors]: %v", err)
}
if setting.Cron.UpdateMirror.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go WithUnique(mirrorUpdate, mirror_service.Update)()
}
}
if setting.Cron.RepoHealthCheck.Enabled {
entry, err = c.AddFunc("Repository health check", setting.Cron.RepoHealthCheck.Schedule, WithUnique(gitFsck, func(ctx context.Context) {
if err := repo_module.GitFsck(ctx); err != nil {
log.Error("GitFsck: %s", err)
}
}))
if err != nil {
log.Fatal("Cron[Repository health check]: %v", err)
}
if setting.Cron.RepoHealthCheck.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go WithUnique(gitFsck, func(ctx context.Context) {
if err := repo_module.GitFsck(ctx); err != nil {
log.Error("GitFsck: %s", err)
}
})()
}
}
if setting.Cron.CheckRepoStats.Enabled {
entry, err = c.AddFunc("Check repository statistics", setting.Cron.CheckRepoStats.Schedule, WithUnique(checkRepos, models.CheckRepoStats))
if err != nil {
log.Fatal("Cron[Check repository statistics]: %v", err)
}
if setting.Cron.CheckRepoStats.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go WithUnique(checkRepos, models.CheckRepoStats)()
}
}
if setting.Cron.ArchiveCleanup.Enabled {
entry, err = c.AddFunc("Clean up old repository archives", setting.Cron.ArchiveCleanup.Schedule, WithUnique(archiveCleanup, models.DeleteOldRepositoryArchives))
if err != nil {
log.Fatal("Cron[Clean up old repository archives]: %v", err)
}
if setting.Cron.ArchiveCleanup.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go WithUnique(archiveCleanup, models.DeleteOldRepositoryArchives)()
}
}
if setting.Cron.SyncExternalUsers.Enabled {
entry, err = c.AddFunc("Synchronize external users", setting.Cron.SyncExternalUsers.Schedule, WithUnique(syncExternalUsers, models.SyncExternalUsers))
if err != nil {
log.Fatal("Cron[Synchronize external users]: %v", err)
}
if setting.Cron.SyncExternalUsers.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go WithUnique(syncExternalUsers, models.SyncExternalUsers)()
}
}
if setting.Cron.DeletedBranchesCleanup.Enabled {
entry, err = c.AddFunc("Remove old deleted branches", setting.Cron.DeletedBranchesCleanup.Schedule, WithUnique(deletedBranchesCleanup, models.RemoveOldDeletedBranches))
if err != nil {
log.Fatal("Cron[Remove old deleted branches]: %v", err)
}
if setting.Cron.DeletedBranchesCleanup.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go WithUnique(deletedBranchesCleanup, models.RemoveOldDeletedBranches)()
}
}
entry, err = c.AddFunc("Update migrated repositories' issues and comments' posterid", setting.Cron.UpdateMigrationPosterID.Schedule, WithUnique(updateMigrationPosterID, migrations.UpdateMigrationPosterID))
if err != nil {
log.Fatal("Cron[Update migrated repositories]: %v", err)
}
entry.Prev = time.Now()
entry.ExecTimes++
go WithUnique(updateMigrationPosterID, migrations.UpdateMigrationPosterID)()
c.Start()
graceful.GetManager().RunAtShutdown(context.Background(), c.Stop)
}
// ListTasks returns all running cron tasks.
func ListTasks() []*cron.Entry {
return c.Entries()
}
|