aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2022-03-29 02:31:07 +0100
committerGitHub <noreply@github.com>2022-03-29 02:31:07 +0100
commit90e0a402c1185827fd3d5352ca915c531ce1e7b1 (patch)
treeaa27fa1774c1c3af797d86a08e829d30bdb8010a
parente69b7a92ed91a4b078d216581a24497a72363494 (diff)
downloadgitea-90e0a402c1185827fd3d5352ca915c531ce1e7b1.tar.gz
gitea-90e0a402c1185827fd3d5352ca915c531ce1e7b1.zip
Show last cron messages on monitor page (#19223)
As discussed on #19221 we should store the results of the last task message on the crontask and show them on the monitor page. Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
-rw-r--r--options/locale/locale_en-US.ini1
-rw-r--r--services/cron/cron.go36
-rw-r--r--services/cron/setting.go19
-rw-r--r--services/cron/tasks.go50
-rw-r--r--templates/admin/cron.tmpl35
-rw-r--r--templates/admin/monitor.tmpl35
6 files changed, 109 insertions, 67 deletions
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 5008cd2bab..0a4abde408 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2816,6 +2816,7 @@ monitor.process = Running Processes
monitor.desc = Description
monitor.start = Start Time
monitor.execute_time = Execution Time
+monitor.last_execution_result = Result
monitor.process.cancel = Cancel process
monitor.process.cancel_desc = Cancelling a process may cause data loss
monitor.process.cancel_notices = Cancel: <strong>%s</strong>?
diff --git a/services/cron/cron.go b/services/cron/cron.go
index 19f703caf1..9fe90d4230 100644
--- a/services/cron/cron.go
+++ b/services/cron/cron.go
@@ -47,11 +47,23 @@ func NewContext() {
// TaskTableRow represents a task row in the tasks table
type TaskTableRow struct {
- Name string
- Spec string
- Next time.Time
- Prev time.Time
- ExecTimes int64
+ Name string
+ Spec string
+ Next time.Time
+ Prev time.Time
+ Status string
+ LastMessage string
+ LastDoer string
+ ExecTimes int64
+ task *Task
+}
+
+func (t *TaskTableRow) FormatLastMessage(locale string) string {
+ if t.Status == "finished" {
+ return t.task.GetConfig().FormatMessage(locale, t.Name, t.Status, t.LastDoer)
+ }
+
+ return t.task.GetConfig().FormatMessage(locale, t.Name, t.Status, t.LastDoer, t.LastMessage)
}
// TaskTable represents a table of tasks
@@ -80,11 +92,15 @@ func ListTasks() TaskTable {
}
task.lock.Lock()
tTable = append(tTable, &TaskTableRow{
- Name: task.Name,
- Spec: spec,
- Next: next,
- Prev: prev,
- ExecTimes: task.ExecTimes,
+ Name: task.Name,
+ Spec: spec,
+ Next: next,
+ Prev: prev,
+ ExecTimes: task.ExecTimes,
+ LastMessage: task.LastMessage,
+ Status: task.Status,
+ LastDoer: task.LastDoer,
+ task: task,
})
task.lock.Unlock()
}
diff --git a/services/cron/setting.go b/services/cron/setting.go
index 4ccb7c7ce3..f0683393ff 100644
--- a/services/cron/setting.go
+++ b/services/cron/setting.go
@@ -7,8 +7,6 @@ package cron
import (
"time"
- user_model "code.gitea.io/gitea/models/user"
-
"github.com/unknwon/i18n"
)
@@ -17,7 +15,7 @@ type Config interface {
IsEnabled() bool
DoRunAtStart() bool
GetSchedule() string
- FormatMessage(name, status string, doer *user_model.User, args ...interface{}) string
+ FormatMessage(locale, name, status, doer string, args ...interface{}) string
DoNoticeOnSuccess() bool
}
@@ -70,19 +68,20 @@ func (b *BaseConfig) DoNoticeOnSuccess() bool {
}
// FormatMessage returns a message for the task
-func (b *BaseConfig) FormatMessage(name, status string, doer *user_model.User, args ...interface{}) string {
+// Please note the `status` string will be concatenated with `admin.dashboard.cron.` and `admin.dashboard.task.` to provide locale messages. Similarly `name` will be composed with `admin.dashboard.` to provide the locale name for the task.
+func (b *BaseConfig) FormatMessage(locale, name, status, doer string, args ...interface{}) string {
realArgs := make([]interface{}, 0, len(args)+2)
- realArgs = append(realArgs, i18n.Tr("en-US", "admin.dashboard."+name))
- if doer == nil {
+ realArgs = append(realArgs, i18n.Tr(locale, "admin.dashboard."+name))
+ if doer == "" {
realArgs = append(realArgs, "(Cron)")
} else {
- realArgs = append(realArgs, doer.Name)
+ realArgs = append(realArgs, doer)
}
if len(args) > 0 {
realArgs = append(realArgs, args...)
}
- if doer == nil || (doer.ID == -1 && doer.Name == "(Cron)") {
- return i18n.Tr("en-US", "admin.dashboard.cron."+status, realArgs...)
+ if doer == "" {
+ return i18n.Tr(locale, "admin.dashboard.cron."+status, realArgs...)
}
- return i18n.Tr("en-US", "admin.dashboard.task."+status, realArgs...)
+ return i18n.Tr(locale, "admin.dashboard.task."+status, realArgs...)
}
diff --git a/services/cron/tasks.go b/services/cron/tasks.go
index 070fb6e9e1..2252ad21e2 100644
--- a/services/cron/tasks.go
+++ b/services/cron/tasks.go
@@ -29,11 +29,14 @@ var (
// Task represents a Cron task
type Task struct {
- lock sync.Mutex
- Name string
- config Config
- fun func(context.Context, *user_model.User, Config) error
- ExecTimes int64
+ lock sync.Mutex
+ Name string
+ config Config
+ fun func(context.Context, *user_model.User, Config) error
+ Status string
+ LastMessage string
+ LastDoer string
+ ExecTimes int64
}
// DoRunAtStart returns if this task should run at the start
@@ -86,24 +89,45 @@ func (t *Task) RunWithUser(doer *user_model.User, config Config) {
}()
graceful.GetManager().RunWithShutdownContext(func(baseCtx context.Context) {
pm := process.GetManager()
- ctx, _, finished := pm.AddContext(baseCtx, config.FormatMessage(t.Name, "process", doer))
+ doerName := ""
+ if doer != nil && doer.ID != -1 {
+ doerName = doer.Name
+ }
+
+ ctx, _, finished := pm.AddContext(baseCtx, config.FormatMessage("en-US", t.Name, "process", doerName))
defer finished()
if err := t.fun(ctx, doer, config); err != nil {
+ var message string
+ var status string
if db.IsErrCancelled(err) {
- message := err.(db.ErrCancelled).Message
- if err := admin_model.CreateNotice(ctx, admin_model.NoticeTask, config.FormatMessage(t.Name, "aborted", doer, message)); err != nil {
- log.Error("CreateNotice: %v", err)
- }
- return
+ status = "cancelled"
+ message = err.(db.ErrCancelled).Message
+ } else {
+ status = "error"
+ message = err.Error()
}
- if err := admin_model.CreateNotice(ctx, admin_model.NoticeTask, config.FormatMessage(t.Name, "error", doer, err)); err != nil {
+
+ t.lock.Lock()
+ t.LastMessage = message
+ t.Status = status
+ t.LastDoer = doerName
+ t.lock.Unlock()
+
+ if err := admin_model.CreateNotice(ctx, admin_model.NoticeTask, config.FormatMessage("en-US", t.Name, "cancelled", doerName, message)); err != nil {
log.Error("CreateNotice: %v", err)
}
return
}
+
+ t.lock.Lock()
+ t.Status = "finished"
+ t.LastMessage = ""
+ t.LastDoer = doerName
+ t.lock.Unlock()
+
if config.DoNoticeOnSuccess() {
- if err := admin_model.CreateNotice(ctx, admin_model.NoticeTask, config.FormatMessage(t.Name, "finished", doer)); err != nil {
+ if err := admin_model.CreateNotice(ctx, admin_model.NoticeTask, config.FormatMessage("en-US", t.Name, "finished", doerName)); err != nil {
log.Error("CreateNotice: %v", err)
}
}
diff --git a/templates/admin/cron.tmpl b/templates/admin/cron.tmpl
new file mode 100644
index 0000000000..30277177ed
--- /dev/null
+++ b/templates/admin/cron.tmpl
@@ -0,0 +1,35 @@
+<h4 class="ui top attached header">
+ {{.i18n.Tr "admin.monitor.cron"}}
+</h4>
+<div class="ui attached table segment">
+ <form method="post" action="{{AppSubUrl}}/admin">
+ <table class="ui very basic striped table">
+ <thead>
+ <tr>
+ <th></th>
+ <th>{{.i18n.Tr "admin.monitor.name"}}</th>
+ <th>{{.i18n.Tr "admin.monitor.schedule"}}</th>
+ <th>{{.i18n.Tr "admin.monitor.next"}}</th>
+ <th>{{.i18n.Tr "admin.monitor.previous"}}</th>
+ <th>{{.i18n.Tr "admin.monitor.execute_times"}}</th>
+ <th>{{.i18n.Tr "admin.monitor.last_execution_result"}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{range .Entries}}
+ <tr>
+ <td><button type="submit" class="ui green button" name="op" value="{{.Name}}" title="{{$.i18n.Tr "admin.dashboard.operation_run"}}">{{svg "octicon-triangle-right"}}</button></td>
+ <td>{{$.i18n.Tr (printf "admin.dashboard.%s" .Name)}}</td>
+ <td>{{.Spec}}</td>
+ <td>{{DateFmtLong .Next}}</td>
+ <td>{{if gt .Prev.Year 1 }}{{DateFmtLong .Prev}}{{else}}N/A{{end}}</td>
+ <td>{{.ExecTimes}}</td>
+ <td {{if ne .Status ""}}class="tooltip" data-content="{{.FormatLastMessage $.i18n.Language}}"{{end}} >{{if eq .Status "" }}—{{else if eq .Status "finished"}}{{svg "octicon-check" 16}}{{else}}{{svg "octicon-x" 16}}{{end}}</td>
+ </tr>
+ {{end}}
+ </tbody>
+ </table>
+ <input type="hidden" name="from" value="monitor"/>
+ {{.CsrfTokenHtml}}
+ </form>
+</div>
diff --git a/templates/admin/monitor.tmpl b/templates/admin/monitor.tmpl
index a35b587bd5..443159f8ce 100644
--- a/templates/admin/monitor.tmpl
+++ b/templates/admin/monitor.tmpl
@@ -3,40 +3,7 @@
{{template "admin/navbar" .}}
<div class="ui container">
{{template "base/alert" .}}
- <h4 class="ui top attached header">
- {{.i18n.Tr "admin.monitor.cron"}}
- </h4>
- <div class="ui attached table segment">
- <form method="post" action="{{AppSubUrl}}/admin">
- <table class="ui very basic striped table">
- <thead>
- <tr>
- <th></th>
- <th>{{.i18n.Tr "admin.monitor.name"}}</th>
- <th>{{.i18n.Tr "admin.monitor.schedule"}}</th>
- <th>{{.i18n.Tr "admin.monitor.next"}}</th>
- <th>{{.i18n.Tr "admin.monitor.previous"}}</th>
- <th>{{.i18n.Tr "admin.monitor.execute_times"}}</th>
- </tr>
- </thead>
- <tbody>
- {{range .Entries}}
- <tr>
- <td><button type="submit" class="ui green button" name="op" value="{{.Name}}" title="{{$.i18n.Tr "admin.dashboard.operation_run"}}">{{svg "octicon-triangle-right"}}</button></td>
- <td>{{$.i18n.Tr (printf "admin.dashboard.%s" .Name)}}</td>
- <td>{{.Spec}}</td>
- <td>{{DateFmtLong .Next}}</td>
- <td>{{if gt .Prev.Year 1 }}{{DateFmtLong .Prev}}{{else}}N/A{{end}}</td>
- <td>{{.ExecTimes}}</td>
- </tr>
- {{end}}
- </tbody>
- </table>
- <input type="hidden" name="from" value="monitor"/>
- {{.CsrfTokenHtml}}
- </form>
- </div>
-
+ {{template "admin/cron" .}}
<h4 class="ui top attached header">
{{.i18n.Tr "admin.monitor.queues"}}
</h4>