1Panel/agent/app/service/cronjob.go

777 lines
23 KiB
Go

package service
import (
"context"
"encoding/json"
"fmt"
"os"
"path"
"strconv"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/robfig/cron/v3"
)
type CronjobService struct{}
type ICronjobService interface {
SearchWithPage(search dto.PageCronjob) (int64, interface{}, error)
SearchRecords(search dto.SearchRecord) (int64, interface{}, error)
Create(cronjobDto dto.CronjobOperate) error
LoadNextHandle(spec string) ([]string, error)
HandleOnce(id uint) error
Update(id uint, req dto.CronjobOperate) error
UpdateStatus(id uint, status string) error
UpdateGroup(req dto.ChangeGroup) error
Delete(req dto.CronjobBatchDelete) error
StartJob(cronjob *model.Cronjob, isUpdate bool) (string, error)
CleanRecord(req dto.CronjobClean) error
Export(req dto.OperateByIDs) (string, error)
Import(req []dto.CronjobTrans) error
LoadScriptOptions() []dto.ScriptOptions
LoadInfo(req dto.OperateByID) (*dto.CronjobOperate, error)
LoadRecordLog(req dto.OperateByID) string
}
func NewICronjobService() ICronjobService {
return &CronjobService{}
}
func (u *CronjobService) SearchWithPage(search dto.PageCronjob) (int64, interface{}, error) {
total, cronjobs, err := cronjobRepo.Page(search.Page,
search.PageSize,
repo.WithByGroups(search.GroupIDs),
repo.WithByLikeName(search.Info),
repo.WithOrderRuleBy(search.OrderBy, search.Order))
var dtoCronjobs []dto.CronjobInfo
for _, cronjob := range cronjobs {
var item dto.CronjobInfo
if err := copier.Copy(&item, &cronjob); err != nil {
return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
record, _ := cronjobRepo.RecordFirst(cronjob.ID)
if record.ID != 0 {
item.LastRecordStatus = record.Status
item.LastRecordTime = record.StartTime.Format(constant.DateTimeLayout)
} else {
item.LastRecordTime = "-"
}
item.SourceAccounts, item.DownloadAccount, _ = loadBackupNamesByID(cronjob.SourceAccountIDs, cronjob.DownloadAccountID)
alertBase := dto.AlertBase{
AlertType: cronjob.Type,
EntryID: cronjob.ID,
}
alertInfo, _ := alertRepo.Get(alertRepo.WithByType(alertBase.AlertType), alertRepo.WithByProject(strconv.Itoa(int(alertBase.EntryID))), repo.WithByStatus(constant.AlertEnable))
if alertInfo.SendCount != 0 {
item.AlertCount = alertInfo.SendCount
} else {
item.AlertCount = 0
}
if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 {
_ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule)
}
dtoCronjobs = append(dtoCronjobs, item)
}
return total, dtoCronjobs, err
}
func (u *CronjobService) LoadInfo(req dto.OperateByID) (*dto.CronjobOperate, error) {
cronjob, err := cronjobRepo.Get(repo.WithByID(req.ID))
var item dto.CronjobOperate
if err := copier.Copy(&item, &cronjob); err != nil {
return nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
alertBase := dto.AlertBase{
AlertType: cronjob.Type,
EntryID: cronjob.ID,
}
alertInfo, _ := alertRepo.Get(alertRepo.WithByType(alertBase.AlertType), alertRepo.WithByProject(strconv.Itoa(int(alertBase.EntryID))), repo.WithByStatus(constant.AlertEnable))
item.AlertMethod = alertInfo.Method
if alertInfo.SendCount != 0 {
item.AlertCount = alertInfo.SendCount
} else {
item.AlertCount = 0
}
if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 {
_ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule)
}
return &item, err
}
func (u *CronjobService) Export(req dto.OperateByIDs) (string, error) {
cronjobs, err := cronjobRepo.List(repo.WithByIDs(req.IDs))
if err != nil {
return "", err
}
var data []dto.CronjobTrans
for _, cronjob := range cronjobs {
item := dto.CronjobTrans{
Name: cronjob.Name,
Type: cronjob.Type,
GroupID: cronjob.GroupID,
SpecCustom: cronjob.SpecCustom,
Spec: cronjob.Spec,
Executor: cronjob.Executor,
ScriptMode: cronjob.ScriptMode,
Script: cronjob.Script,
Command: cronjob.Command,
ContainerName: cronjob.ContainerName,
User: cronjob.User,
URL: cronjob.URL,
DBType: cronjob.DBType,
ExclusionRules: cronjob.ExclusionRules,
IsDir: cronjob.IsDir,
SourceDir: cronjob.SourceDir,
RetainCopies: cronjob.RetainCopies,
RetryTimes: cronjob.RetryTimes,
Timeout: cronjob.Timeout,
IgnoreErr: cronjob.IgnoreErr,
Secret: cronjob.Secret,
}
switch cronjob.Type {
case "app":
if cronjob.AppID == "all" {
break
}
apps := loadAppsForJob(cronjob)
for _, app := range apps {
item.Apps = append(item.Apps, dto.TransHelper{Name: app.App.Key, DetailName: app.Name})
}
case "website", "cutWebsiteLog":
if cronjob.Website == "all" {
break
}
websites := loadWebsForJob(cronjob)
for _, website := range websites {
item.Websites = append(item.Websites, website.Alias)
}
case "database":
if cronjob.DBName == "all" {
break
}
databases := loadDbsForJob(cronjob)
for _, db := range databases {
item.DBNames = append(item.DBNames, dto.TransHelper{Name: db.Database, DetailName: db.Name})
}
case "shell":
if cronjob.ScriptMode == "library" {
script, err := scriptRepo.Get(repo.WithByID(cronjob.ScriptID))
if err != nil {
return "", err
}
item.ScriptName = script.Name
}
case "snapshot":
if len(cronjob.SnapshotRule) == 0 {
break
}
var snapRule dto.SnapshotRule
if err := json.Unmarshal([]byte(cronjob.SnapshotRule), &snapRule); err != nil {
return "", err
}
item.SnapshotRule.WithImage = snapRule.WithImage
if len(snapRule.IgnoreAppIDs) != 0 {
ignoreApps, _ := appInstallRepo.ListBy(context.Background(), repo.WithByIDs(snapRule.IgnoreAppIDs))
for _, app := range ignoreApps {
item.SnapshotRule.IgnoreApps = append(item.SnapshotRule.IgnoreApps, dto.TransHelper{Name: app.App.Key, DetailName: app.Name})
}
}
}
item.SourceAccounts, item.DownloadAccount, _ = loadBackupNamesByID(cronjob.SourceAccountIDs, cronjob.DownloadAccountID)
alertInfo, _ := alertRepo.Get(alertRepo.WithByType(cronjob.Type), alertRepo.WithByProject(strconv.Itoa(int(cronjob.ID))), repo.WithByStatus(constant.AlertEnable))
if alertInfo.SendCount != 0 {
item.AlertCount = alertInfo.SendCount
item.AlertTitle = alertInfo.Title
item.AlertMethod = alertInfo.Method
} else {
item.AlertCount = 0
}
data = append(data, item)
}
itemJson, err := json.Marshal(&data)
if err != nil {
return "", err
}
return string(itemJson), nil
}
func (u *CronjobService) Import(req []dto.CronjobTrans) error {
for _, item := range req {
cronjobItem, _ := cronjobRepo.Get(repo.WithByName(item.Name))
if cronjobItem.ID != 0 {
continue
}
cronjob := model.Cronjob{
Name: item.Name,
Type: item.Type,
GroupID: item.GroupID,
SpecCustom: item.SpecCustom,
Spec: item.Spec,
Executor: item.Executor,
ScriptMode: item.ScriptMode,
Command: item.Command,
ContainerName: item.ContainerName,
User: item.User,
URL: item.URL,
DBType: item.DBType,
ExclusionRules: item.ExclusionRules,
IsDir: item.IsDir,
RetainCopies: item.RetainCopies,
RetryTimes: item.RetryTimes,
Timeout: item.Timeout,
IgnoreErr: item.IgnoreErr,
Secret: item.Secret,
}
hasNotFound := false
switch item.Type {
case "app":
if len(item.Apps) == 0 {
cronjob.AppID = "all"
break
}
var appIDs []string
for _, app := range item.Apps {
appItem, err := appInstallRepo.LoadInstallAppByKeyAndName(app.Name, app.DetailName)
if err != nil {
hasNotFound = true
continue
}
appIDs = append(appIDs, fmt.Sprintf("%v", appItem.ID))
}
cronjob.AppID = strings.Join(appIDs, ",")
case "website", "cutWebsiteLog":
if len(item.Websites) == 0 {
cronjob.Website = "all"
break
}
var webIDs []string
for _, web := range item.Websites {
webItem, err := websiteRepo.GetFirst(websiteRepo.WithAlias(web))
if err != nil {
hasNotFound = true
continue
}
webIDs = append(webIDs, fmt.Sprintf("%v", webItem.ID))
}
cronjob.Website = strings.Join(webIDs, ",")
case "database":
if len(item.DBNames) == 0 {
cronjob.DBName = "all"
break
}
var dbIDs []string
if strings.Contains(cronjob.DBType, "postgresql") {
for _, db := range item.DBNames {
dbItem, err := postgresqlRepo.Get(postgresqlRepo.WithByPostgresqlName(db.Name), repo.WithByName(db.DetailName))
if err != nil {
hasNotFound = true
continue
}
dbIDs = append(dbIDs, fmt.Sprintf("%v", dbItem.ID))
}
} else {
for _, db := range item.DBNames {
dbItem, err := mysqlRepo.Get(mysqlRepo.WithByMysqlName(db.Name), repo.WithByName(db.DetailName))
if err != nil {
hasNotFound = true
continue
}
dbIDs = append(dbIDs, fmt.Sprintf("%v", dbItem.ID))
}
}
cronjob.DBName = strings.Join(dbIDs, ",")
case "shell":
if len(item.ContainerName) != 0 {
cronjob.Script = item.Script
client, err := docker.NewDockerClient()
if err != nil {
hasNotFound = true
break
}
defer client.Close()
if _, err := client.ContainerStats(context.Background(), item.ContainerName, false); err != nil {
hasNotFound = true
break
}
}
switch item.ScriptMode {
case "library":
library, _ := scriptRepo.Get(repo.WithByName(item.ScriptName))
if library.ID == 0 {
hasNotFound = true
break
}
cronjob.ScriptID = library.ID
case "select":
if _, err := os.Stat(item.Script); err != nil {
hasNotFound = true
break
}
cronjob.Script = item.Script
case "input":
cronjob.Script = item.Script
}
case "directory":
if item.IsDir {
if _, err := os.Stat(item.SourceDir); err != nil {
hasNotFound = true
break
}
cronjob.SourceDir = item.SourceDir
} else {
fileList := strings.Split(item.SourceDir, ",")
var newFiles []string
for _, item := range fileList {
if len(item) == 0 {
continue
}
if _, err := os.Stat(item); err != nil {
hasNotFound = true
continue
}
newFiles = append(newFiles, item)
}
cronjob.SourceDir = strings.Join(newFiles, ",")
}
case "snapshot":
if len(item.SnapshotRule.IgnoreApps) == 0 && !item.SnapshotRule.WithImage {
break
}
var itemRules dto.SnapshotRule
itemRules.WithImage = item.SnapshotRule.WithImage
for _, app := range item.SnapshotRule.IgnoreApps {
appItem, err := appInstallRepo.LoadInstallAppByKeyAndName(app.Name, app.DetailName)
if err != nil {
hasNotFound = true
continue
}
itemRules.IgnoreAppIDs = append(itemRules.IgnoreAppIDs, appItem.ID)
}
itemRulesStr, _ := json.Marshal(itemRules)
cronjob.SnapshotRule = string(itemRulesStr)
}
var acIDs []string
for _, ac := range item.SourceAccounts {
backup, err := backupRepo.Get(repo.WithByName(ac))
if err != nil {
hasNotFound = true
continue
}
if ac == item.DownloadAccount {
cronjob.DownloadAccountID = backup.ID
}
acIDs = append(acIDs, fmt.Sprintf("%v", backup.ID))
}
cronjob.SourceAccountIDs = strings.Join(acIDs, ",")
if hasNotFound {
cronjob.Status = constant.StatusPending
} else {
cronjob.Status = constant.StatusDisable
}
_ = cronjobRepo.Create(&cronjob)
if item.AlertCount != 0 && item.AlertTitle != "" && item.AlertMethod != "" {
createAlert := dto.AlertCreate{
Title: item.AlertTitle,
SendCount: item.AlertCount,
Method: item.AlertMethod,
Type: cronjob.Type,
Project: strconv.Itoa(int(cronjob.ID)),
Status: constant.AlertEnable,
}
_ = NewIAlertService().CreateAlert(createAlert)
}
}
return nil
}
func (u *CronjobService) LoadScriptOptions() []dto.ScriptOptions {
scripts, err := scriptRepo.List()
if err != nil {
return nil
}
lang, _ := settingRepo.GetValueByKey("Language")
if len(lang) == 0 {
lang = "en"
}
var options []dto.ScriptOptions
for _, script := range scripts {
var item dto.ScriptOptions
item.ID = script.ID
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(script.Name), &translations)
if name, ok := translations[lang]; ok {
item.Name = strings.ReplaceAll(name, " ", "_")
} else {
item.Name = strings.ReplaceAll(script.Name, " ", "_")
}
options = append(options, item)
}
return options
}
func (u *CronjobService) SearchRecords(search dto.SearchRecord) (int64, interface{}, error) {
total, records, err := cronjobRepo.PageRecords(
search.Page,
search.PageSize,
repo.WithByStatus(search.Status),
cronjobRepo.WithByJobID(search.CronjobID),
repo.WithByDate(search.StartTime, search.EndTime))
var dtoCronjobs []dto.Record
for _, record := range records {
var item dto.Record
if err := copier.Copy(&item, &record); err != nil {
return 0, nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
item.StartTime = record.StartTime.Format(constant.DateTimeLayout)
dtoCronjobs = append(dtoCronjobs, item)
}
return total, dtoCronjobs, err
}
func (u *CronjobService) LoadNextHandle(specStr string) ([]string, error) {
spec := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
now := time.Now()
var nexts [5]string
if strings.HasPrefix(specStr, "@every ") {
duration := time.Minute
if strings.HasSuffix(specStr, "s") {
duration = time.Second
}
interval := strings.ReplaceAll(specStr, "@every ", "")
interval = strings.ReplaceAll(interval, "s", "")
interval = strings.ReplaceAll(interval, "m", "")
durationItem, err := strconv.Atoi(interval)
if err != nil {
return nil, err
}
for i := 0; i < 5; i++ {
nextTime := now.Add(time.Duration(durationItem) * duration)
nexts[i] = nextTime.Format(constant.DateTimeLayout)
now = nextTime
}
return nexts[:], nil
}
sched, err := spec.Parse(specStr)
if err != nil {
return nil, err
}
for i := 0; i < 5; i++ {
nextTime := sched.Next(now)
nexts[i] = nextTime.Format(constant.DateTimeLayout)
now = nextTime
}
return nexts[:], nil
}
func (u *CronjobService) LoadRecordLog(req dto.OperateByID) string {
record, err := cronjobRepo.GetRecord(repo.WithByID(req.ID))
if err != nil {
return ""
}
if _, err := os.Stat(record.Records); err != nil {
return ""
}
content, err := os.ReadFile(record.Records)
if err != nil {
return ""
}
return string(content)
}
func (u *CronjobService) CleanRecord(req dto.CronjobClean) error {
cronjob, err := cronjobRepo.Get(repo.WithByID(req.CronjobID))
if err != nil {
return err
}
if req.CleanData {
if hasBackup(cronjob.Type) {
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if err != nil {
return err
}
if !req.CleanRemoteData {
for key := range accountMap {
if key != constant.Local {
delete(accountMap, key)
}
}
}
cronjob.RetainCopies = 0
if len(accountMap) != 0 {
u.removeExpiredBackup(cronjob, accountMap, model.BackupRecord{})
}
}
}
if req.IsDelete {
records, _ := backupRepo.ListRecord(backupRepo.WithByCronID(cronjob.ID))
for _, records := range records {
records.CronjobID = 0
_ = backupRepo.UpdateRecord(&records)
}
}
delRecords, err := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(req.CronjobID)))
if err != nil {
return err
}
for _, del := range delRecords {
_ = os.RemoveAll(del.Records)
}
if err := cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(req.CronjobID))); err != nil {
return err
}
return nil
}
func (u *CronjobService) HandleOnce(id uint) error {
cronjob, _ := cronjobRepo.Get(repo.WithByID(id))
if cronjob.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
u.HandleJob(&cronjob)
return nil
}
func (u *CronjobService) Create(req dto.CronjobOperate) error {
cronjob, _ := cronjobRepo.Get(repo.WithByName(req.Name))
if cronjob.ID != 0 {
return buserr.New("ErrRecordExist")
}
cronjob.Secret = req.Secret
if err := copier.Copy(&cronjob, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
if cronjob.Type == "snapshot" {
rule, err := json.Marshal(req.SnapshotRule)
if err != nil {
return err
}
cronjob.SnapshotRule = string(rule)
}
if cronjob.Type == "cutWebsiteLog" {
backupAccount, err := backupRepo.Get(repo.WithByType(constant.Local))
if backupAccount.ID == 0 {
return fmt.Errorf("load local backup dir failed, err: %v", err)
}
cronjob.DownloadAccountID, cronjob.SourceAccountIDs = backupAccount.ID, fmt.Sprintf("%v", backupAccount.ID)
}
cronjob.Status = constant.StatusEnable
global.LOG.Infof("create cronjob %s successful, spec: %s", cronjob.Name, cronjob.Spec)
spec := cronjob.Spec
entryIDs, err := u.StartJob(&cronjob, false)
if err != nil {
return err
}
cronjob.Spec = spec
cronjob.EntryIDs = entryIDs
if err := cronjobRepo.Create(&cronjob); err != nil {
return err
}
if req.AlertCount != 0 && req.AlertTitle != "" && req.AlertMethod != "" {
createAlert := dto.AlertCreate{
Title: req.AlertTitle,
SendCount: req.AlertCount,
Method: req.AlertMethod,
Type: cronjob.Type,
Project: strconv.Itoa(int(cronjob.ID)),
Status: constant.AlertEnable,
}
err := NewIAlertService().CreateAlert(createAlert)
if err != nil {
return err
}
}
return nil
}
func (u *CronjobService) StartJob(cronjob *model.Cronjob, isUpdate bool) (string, error) {
if len(cronjob.EntryIDs) != 0 && isUpdate {
ids := strings.Split(cronjob.EntryIDs, ",")
for _, id := range ids {
idItem, _ := strconv.Atoi(id)
global.Cron.Remove(cron.EntryID(idItem))
}
}
specs := strings.Split(cronjob.Spec, ",")
var ids []string
for _, spec := range specs {
cronjob.Spec = spec
entryID, err := u.AddCronJob(cronjob)
if err != nil {
return "", err
}
ids = append(ids, fmt.Sprintf("%v", entryID))
}
return strings.Join(ids, ","), nil
}
func (u *CronjobService) Delete(req dto.CronjobBatchDelete) error {
for _, id := range req.IDs {
cronjob, _ := cronjobRepo.Get(repo.WithByID(id))
if cronjob.ID == 0 {
return errors.New("find cronjob in db failed")
}
_ = os.RemoveAll(path.Join(global.Dir.DataDir, "task/shell", cronjob.Name))
ids := strings.Split(cronjob.EntryIDs, ",")
for _, id := range ids {
idItem, _ := strconv.Atoi(id)
global.Cron.Remove(cron.EntryID(idItem))
}
global.LOG.Infof("stop cronjob entryID: %s", cronjob.EntryIDs)
if err := u.CleanRecord(dto.CronjobClean{CronjobID: id, CleanData: req.CleanData, CleanRemoteData: req.CleanRemoteData, IsDelete: true}); err != nil {
return err
}
if err := cronjobRepo.Delete(repo.WithByID(id)); err != nil {
return err
}
err := alertRepo.Delete(alertRepo.WithByProject(strconv.Itoa(int(cronjob.ID))), alertRepo.WithByType(cronjob.Type))
if err != nil {
return err
}
}
return nil
}
func (u *CronjobService) Update(id uint, req dto.CronjobOperate) error {
var cronjob model.Cronjob
if err := copier.Copy(&cronjob, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
}
if req.Type == "snapshot" {
itemRule, err := json.Marshal(req.SnapshotRule)
if err != nil {
return err
}
cronjob.SnapshotRule = string(itemRule)
}
cronModel, err := cronjobRepo.Get(repo.WithByID(id))
if err != nil {
return buserr.New("ErrRecordNotFound")
}
upMap := make(map[string]interface{})
cronjob.EntryIDs = cronModel.EntryIDs
cronjob.Type = cronModel.Type
spec := cronjob.Spec
if cronModel.Status == constant.StatusEnable {
newEntryIDs, err := u.StartJob(&cronjob, true)
if err != nil {
return err
}
upMap["entry_ids"] = newEntryIDs
} else {
ids := strings.Split(cronjob.EntryIDs, ",")
for _, id := range ids {
idItem, _ := strconv.Atoi(id)
global.Cron.Remove(cron.EntryID(idItem))
}
}
if cronModel.Status == constant.StatusPending {
upMap["status"] = constant.StatusEnable
}
upMap["name"] = req.Name
upMap["group_id"] = req.GroupID
upMap["spec_custom"] = req.SpecCustom
upMap["spec"] = spec
upMap["script"] = req.Script
upMap["script_mode"] = req.ScriptMode
upMap["command"] = req.Command
upMap["container_name"] = req.ContainerName
upMap["executor"] = req.Executor
upMap["user"] = req.User
upMap["script_id"] = req.ScriptID
upMap["app_id"] = req.AppID
upMap["website"] = req.Website
upMap["exclusion_rules"] = req.ExclusionRules
upMap["db_type"] = req.DBType
upMap["db_name"] = req.DBName
upMap["url"] = req.URL
upMap["is_dir"] = req.IsDir
upMap["source_dir"] = req.SourceDir
upMap["snapshot_rule"] = cronjob.SnapshotRule
upMap["source_account_ids"] = req.SourceAccountIDs
upMap["download_account_id"] = req.DownloadAccountID
upMap["retain_copies"] = req.RetainCopies
upMap["retry_times"] = req.RetryTimes
upMap["timeout"] = req.Timeout
upMap["ignore_err"] = req.IgnoreErr
upMap["secret"] = req.Secret
err = cronjobRepo.Update(id, upMap)
if err != nil {
return err
}
updateAlert := dto.AlertCreate{
Title: req.AlertTitle,
SendCount: req.AlertCount,
Method: req.AlertMethod,
Type: cronjob.Type,
Project: strconv.Itoa(int(cronModel.ID)),
}
err = NewIAlertService().ExternalUpdateAlert(updateAlert)
if err != nil {
return err
}
return nil
}
func (u *CronjobService) UpdateStatus(id uint, status string) error {
cronjob, _ := cronjobRepo.Get(repo.WithByID(id))
if cronjob.ID == 0 {
return errors.WithMessage(buserr.New("ErrRecordNotFound"), "record not found")
}
var (
entryIDs string
err error
)
if status == constant.StatusEnable {
entryIDs, err = u.StartJob(&cronjob, false)
if err != nil {
return err
}
} else {
ids := strings.Split(cronjob.EntryIDs, ",")
for _, id := range ids {
idItem, _ := strconv.Atoi(id)
global.Cron.Remove(cron.EntryID(idItem))
}
global.LOG.Infof("stop cronjob entryID: %s", cronjob.EntryIDs)
}
return cronjobRepo.Update(cronjob.ID, map[string]interface{}{"status": status, "entry_ids": entryIDs})
}
func (u *CronjobService) UpdateGroup(req dto.ChangeGroup) error {
cronjob, _ := cronjobRepo.Get(repo.WithByID(req.ID))
if cronjob.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
return cronjobRepo.Update(cronjob.ID, map[string]interface{}{"group_id": req.GroupID})
}
func (u *CronjobService) AddCronJob(cronjob *model.Cronjob) (int, error) {
addFunc := func() {
u.HandleJob(cronjob)
}
global.LOG.Infof("add %s job %s successful", cronjob.Type, cronjob.Name)
entryID, err := global.Cron.AddFunc(cronjob.Spec, addFunc)
if err != nil {
return 0, err
}
global.LOG.Infof("start cronjob entryID: %d", entryID)
return int(entryID), nil
}