1Panel/agent/app/task/task.go

117 lines
2.7 KiB
Go
Raw Normal View History

2024-07-23 14:48:37 +08:00
package task
import (
"context"
"fmt"
"log"
"os"
"path"
"strconv"
"time"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/i18n"
)
type ActionFunc func() error
type RollbackFunc func()
type Task struct {
Name string
Logger *log.Logger
SubTasks []*SubTask
Rollbacks []RollbackFunc
logFile *os.File
}
type SubTask struct {
Name string
Retry int
Timeout time.Duration
Action ActionFunc
Rollback RollbackFunc
Error error
}
func NewTask(name string, taskType string) (*Task, error) {
logPath := path.Join(constant.LogDir, taskType)
//TODO 增加插入到日志表的逻辑
file, err := os.OpenFile(logPath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return nil, fmt.Errorf("failed to open log file: %w", err)
}
logger := log.New(file, "", log.LstdFlags)
return &Task{Name: name, logFile: file, Logger: logger}, nil
}
func (t *Task) AddSubTask(name string, action ActionFunc, rollback RollbackFunc) {
subTask := &SubTask{Name: name, Retry: 0, Timeout: 10 * time.Minute, Action: action, Rollback: rollback}
t.SubTasks = append(t.SubTasks, subTask)
}
func (t *Task) AddSubTaskWithOps(name string, action ActionFunc, rollback RollbackFunc, retry int, timeout time.Duration) {
subTask := &SubTask{Name: name, Retry: retry, Timeout: timeout, Action: action, Rollback: rollback}
t.SubTasks = append(t.SubTasks, subTask)
}
func (s *SubTask) Execute(logger *log.Logger) bool {
logger.Printf(i18n.GetWithName("SubTaskStart", s.Name))
for i := 0; i < s.Retry+1; i++ {
if i > 0 {
logger.Printf(i18n.GetWithName("TaskRetry", strconv.Itoa(i)))
}
ctx, cancel := context.WithTimeout(context.Background(), s.Timeout)
defer cancel()
done := make(chan error)
go func() {
done <- s.Action()
}()
select {
case <-ctx.Done():
logger.Printf(i18n.GetWithName("TaskTimeout", s.Name))
case err := <-done:
if err != nil {
s.Error = err
logger.Printf(i18n.GetWithNameAndErr("TaskFailed", s.Name, err))
} else {
logger.Printf(i18n.GetWithName("TaskSuccess", s.Name))
return true
}
}
if i == s.Retry {
if s.Rollback != nil {
s.Rollback()
}
}
time.Sleep(1 * time.Second)
}
if s.Error != nil {
s.Error = fmt.Errorf(i18n.GetWithName("TaskFailed", s.Name))
}
return false
}
func (t *Task) Execute() error {
t.Logger.Printf(i18n.GetWithName("TaskStart", t.Name))
var err error
for _, subTask := range t.SubTasks {
if subTask.Execute(t.Logger) {
if subTask.Rollback != nil {
t.Rollbacks = append(t.Rollbacks, subTask.Rollback)
}
} else {
err = subTask.Error
for _, rollback := range t.Rollbacks {
rollback()
}
break
}
}
t.Logger.Printf(i18n.GetWithName("TaskEnd", t.Name))
_ = t.logFile.Close()
return err
}