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>
This commit is contained in:
parent
e69b7a92ed
commit
90e0a402c1
6 changed files with 109 additions and 67 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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...)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue