From a818ebc3670be4ca004b3143633346bab4d11de1 Mon Sep 17 00:00:00 2001 From: zaigie Date: Thu, 14 Mar 2024 14:39:12 +0800 Subject: [PATCH] fix(#190): unix/windows createtime difference --- cmd/pst-agent/main.go | 37 +------------ internal/system/createtime_unix.go | 20 +++++++ internal/system/createtime_windows.go | 29 ++++++++++ internal/system/file.go | 76 +++++++++++++++++++++++++++ internal/task/task.go | 11 ++++ internal/tool/save.go | 2 +- 6 files changed, 138 insertions(+), 37 deletions(-) create mode 100644 internal/system/createtime_unix.go create mode 100644 internal/system/createtime_windows.go diff --git a/cmd/pst-agent/main.go b/cmd/pst-agent/main.go index e3813a4..145b8fe 100644 --- a/cmd/pst-agent/main.go +++ b/cmd/pst-agent/main.go @@ -7,7 +7,6 @@ import ( "os" "os/signal" "path/filepath" - "sort" "strconv" "syscall" "time" @@ -75,7 +74,7 @@ func main() { } _, err = s.NewJob( gocron.DurationJob(60*time.Second), - gocron.NewTask(limitCacheFiles, filepath.Join(os.TempDir(), "pst-agent"), 5), + gocron.NewTask(system.LimitCacheZipFiles, filepath.Join(os.TempDir(), "pst-agent"), 5), ) if err != nil { fmt.Println(err) @@ -98,37 +97,3 @@ func main() { logger.Info("PST-Agent gracefully stopped\n") } - -// limitCacheFiles keeps only the latest `n` zip archives in the cache directory -func limitCacheFiles(cacheDir string, n int) { - files, err := os.ReadDir(cacheDir) - if err != nil { - logger.Errorf("Error reading cache directory: %v\n", err) - return - } - - zipFiles := []os.DirEntry{} - for _, file := range files { - if filepath.Ext(file.Name()) == ".zip" { - zipFiles = append(zipFiles, file) - } - } - - if len(zipFiles) <= n { - return - } - - sort.Slice(zipFiles, func(i, j int) bool { - infoI, _ := zipFiles[i].Info() - infoJ, _ := zipFiles[j].Info() - return infoI.ModTime().After(infoJ.ModTime()) - }) - - for i := n; i < len(zipFiles); i++ { - path := filepath.Join(cacheDir, zipFiles[i].Name()) - err := os.Remove(path) - if err != nil { - logger.Errorf("Failed to delete excess zip file: %v\n", err) - } - } -} diff --git a/internal/system/createtime_unix.go b/internal/system/createtime_unix.go new file mode 100644 index 0000000..571dc27 --- /dev/null +++ b/internal/system/createtime_unix.go @@ -0,0 +1,20 @@ +//go:build !windows + +package system + +import ( + "os" + "time" +) + +func GetFileCreateTime(info os.FileInfo) time.Time { + return info.ModTime() +} + +func GetEntryCreateTime(info os.DirEntry) time.Time { + unixFileInfo, err := info.Info() + if err != nil { + return time.Time{} + } + return unixFileInfo.ModTime() +} diff --git a/internal/system/createtime_windows.go b/internal/system/createtime_windows.go new file mode 100644 index 0000000..899b1a4 --- /dev/null +++ b/internal/system/createtime_windows.go @@ -0,0 +1,29 @@ +//go:build windows + +package system + +import ( + "os" + "syscall" + "time" +) + +func GetFileCreateTime(info os.FileInfo) time.Time { + stat, ok := info.Sys().(*syscall.Win32FileAttributeData) + if !ok { + return time.Time{} + } + return time.Unix(0, stat.CreationTime.Nanoseconds()) +} + +func GetEntryCreateTime(info os.DirEntry) time.Time { + winFileInfo, err := info.Info() + if err != nil { + return time.Time{} + } + stat, ok := winFileInfo.Sys().(*syscall.Win32FileAttributeData) + if !ok { + return time.Time{} + } + return time.Unix(0, stat.CreationTime.Nanoseconds()) +} diff --git a/internal/system/file.go b/internal/system/file.go index f9ae5f9..b33ead5 100644 --- a/internal/system/file.go +++ b/internal/system/file.go @@ -6,7 +6,11 @@ import ( "io" "os" "path/filepath" + "sort" "strings" + "time" + + "github.com/zaigie/palworld-server-tool/internal/logger" ) func CheckIsDir(path string) (bool, error) { @@ -198,3 +202,75 @@ func GetLevelSavFilePath(path string) (string, error) { return foundPath, nil } + +// LimitCacheZipFiles keeps only the latest `n` zip archives in the cache directory +func LimitCacheZipFiles(cacheDir string, n int) { + files, err := os.ReadDir(cacheDir) + if err != nil { + logger.Errorf("Error reading cache directory: %v\n", err) + return + } + + zipFiles := []os.DirEntry{} + for _, file := range files { + if filepath.Ext(file.Name()) == ".zip" { + zipFiles = append(zipFiles, file) + } + } + + if len(zipFiles) <= n { + return + } + + sort.Slice(zipFiles, func(i, j int) bool { + createTimeI := GetEntryCreateTime(zipFiles[i]) + createTimeJ := GetEntryCreateTime(zipFiles[j]) + return createTimeI.After(createTimeJ) + }) + + for i := n; i < len(zipFiles); i++ { + path := filepath.Join(cacheDir, zipFiles[i].Name()) + err := os.Remove(path) + if err != nil { + logger.Errorf("Failed to delete excess zip file: %v\n", err) + } + } +} + +type dirInfo struct { + path string + createTime time.Time +} + +// LimitCacheDir keeps only the latest `n` directories in the cache directory +func LimitCacheDir(cacheDirPrefix string, n int) error { + tempDir := os.TempDir() + entries, err := os.ReadDir(tempDir) + if err != nil { + return err + } + + var dirs []dirInfo + for _, entry := range entries { + if entry.IsDir() && strings.HasPrefix(filepath.Base(entry.Name()), cacheDirPrefix) { + dirPath := filepath.Join(tempDir, entry.Name()) + createTime := GetEntryCreateTime(entry) + dirs = append(dirs, dirInfo{path: dirPath, createTime: createTime}) + } + } + + sort.Slice(dirs, func(i, j int) bool { + return dirs[i].createTime.After(dirs[j].createTime) + }) + + if len(dirs) > n { + for _, dir := range dirs[n:] { + err := os.RemoveAll(dir.path) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/internal/task/task.go b/internal/task/task.go index 09ed6c5..f951df7 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -1,10 +1,13 @@ package task import ( + "os" + "path/filepath" "time" "github.com/google/uuid" "github.com/zaigie/palworld-server-tool/internal/database" + "github.com/zaigie/palworld-server-tool/internal/system" "github.com/go-co-op/gocron/v2" "github.com/spf13/viper" @@ -110,6 +113,14 @@ func Schedule(db *bbolt.DB) { } } + _, err := s.NewJob( + gocron.DurationJob(300*time.Second), + gocron.NewTask(system.LimitCacheDir, filepath.Join(os.TempDir(), "palworldsav-"), 5), + ) + if err != nil { + logger.Errorf("%v\n", err) + } + s.Start() } diff --git a/internal/tool/save.go b/internal/tool/save.go index 9aaf808..22a5f71 100644 --- a/internal/tool/save.go +++ b/internal/tool/save.go @@ -52,7 +52,7 @@ func Decode(file string) error { if err != nil { return err } - defer os.RemoveAll(levelFilePath) + defer os.RemoveAll(filepath.Dir(levelFilePath)) baseUrl := "http://127.0.0.1" if viper.GetBool("web.tls") && !strings.HasSuffix(baseUrl, "/") {