160 lines
3.5 KiB
Go
160 lines
3.5 KiB
Go
package removeFile
|
||
|
||
import (
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"sort"
|
||
"time"
|
||
|
||
"be.ems/lib/log"
|
||
"be.ems/src/framework/cron"
|
||
)
|
||
|
||
var NewProcessor = &BarProcessor{
|
||
progress: 0,
|
||
count: 0,
|
||
}
|
||
|
||
// bar 队列任务处理
|
||
type BarProcessor struct {
|
||
// 任务进度
|
||
progress int
|
||
// 执行次数
|
||
count int
|
||
}
|
||
|
||
type BarParams struct {
|
||
FilePath string `json:"filePath"` // file path
|
||
MaxDays int `json:"maxDays"`
|
||
MaxFiles *int `json:"maxFiles"` // keep max files
|
||
MaxSize *int64 `json:"maxSize"`
|
||
Extras string `json:"extras"` // extras condition for where
|
||
}
|
||
|
||
type FileInfo struct {
|
||
Path string
|
||
Info os.FileInfo
|
||
}
|
||
|
||
func (s *BarProcessor) Execute(data any) (any, error) {
|
||
s.count++
|
||
|
||
options := data.(cron.JobData)
|
||
sysJob := options.SysJob
|
||
var params []BarParams
|
||
|
||
err := json.Unmarshal([]byte(sysJob.TargetParams), ¶ms)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
result := []map[string]any{}
|
||
for _, param := range params {
|
||
res, _ := s.ExecuteOne(param)
|
||
result = append(result, res)
|
||
}
|
||
|
||
// 返回结果,用于记录执行结果
|
||
return map[string]any{
|
||
"result": result,
|
||
}, nil
|
||
}
|
||
|
||
func (s *BarProcessor) ExecuteOne(params BarParams) (map[string]any, error) {
|
||
var maxFiles int = 0
|
||
var maxSize int64 = 0
|
||
if params.MaxFiles != nil {
|
||
maxFiles = *params.MaxFiles
|
||
}
|
||
if params.MaxSize != nil {
|
||
maxSize = int64(*params.MaxSize * 1024 * 1024)
|
||
}
|
||
files, err := getFiles(params.FilePath)
|
||
if err != nil {
|
||
return map[string]any{
|
||
"msg": "failed",
|
||
"err": err.Error(),
|
||
}, err
|
||
}
|
||
|
||
// 获取本地时区
|
||
loc, err := time.LoadLocation("Local")
|
||
if err != nil {
|
||
return map[string]any{
|
||
"msg": "failed",
|
||
"err": err.Error(),
|
||
}, err
|
||
}
|
||
cutoff := time.Now().In(loc).AddDate(0, 0, -params.MaxDays)
|
||
|
||
var oldFiles []FileInfo
|
||
for _, file := range files {
|
||
if file.Info.ModTime().Before(cutoff) {
|
||
oldFiles = append(oldFiles, file)
|
||
}
|
||
}
|
||
|
||
// 按修改时间排序文件(最旧的在前)
|
||
sort.Slice(oldFiles, func(i, j int) bool {
|
||
return oldFiles[i].Info.ModTime().Before(oldFiles[j].Info.ModTime())
|
||
})
|
||
|
||
deleted, errorDel := 0, 0
|
||
|
||
// 删除文件,直到满足文件总数不超过maxFiles个且总大小不超过maxSize的条件
|
||
var totalSize int64
|
||
for i, file := range oldFiles {
|
||
if (maxFiles > 0 && i >= maxFiles) || (maxSize > 0 && totalSize+file.Info.Size() > maxSize) {
|
||
break
|
||
}
|
||
err := os.Remove(file.Path)
|
||
if err != nil {
|
||
log.Error("Error deleting file:", file.Path, err)
|
||
errorDel++
|
||
continue
|
||
}
|
||
totalSize += file.Info.Size()
|
||
deleted++
|
||
}
|
||
|
||
// 如果仍然有超过maxFiles个文件或总大小超过maxSize,继续删除最旧的文件
|
||
remainingFiles := files
|
||
sort.Slice(remainingFiles, func(i, j int) bool {
|
||
return remainingFiles[i].Info.ModTime().Before(remainingFiles[j].Info.ModTime())
|
||
})
|
||
|
||
for (maxFiles > 0 && len(remainingFiles) > maxFiles) || (maxSize > 0 && totalSize > maxSize) {
|
||
file := remainingFiles[0]
|
||
err := os.Remove(file.Path)
|
||
if err != nil {
|
||
log.Error("Error deleting file:", file.Path, err)
|
||
remainingFiles = remainingFiles[1:]
|
||
continue
|
||
}
|
||
totalSize -= file.Info.Size()
|
||
remainingFiles = remainingFiles[1:]
|
||
}
|
||
|
||
// 返回结果,用于记录执行结果
|
||
return map[string]any{
|
||
"msg": "successed",
|
||
"filePath": params.FilePath,
|
||
"deleted": deleted,
|
||
"errorDel": errorDel,
|
||
}, nil
|
||
}
|
||
|
||
func getFiles(dir string) ([]FileInfo, error) {
|
||
var files []FileInfo
|
||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if !info.IsDir() {
|
||
files = append(files, FileInfo{Path: path, Info: info})
|
||
}
|
||
return nil
|
||
})
|
||
return files, err
|
||
}
|