Skip to content

Commit

Permalink
fix(#190): unix/windows createtime difference
Browse files Browse the repository at this point in the history
  • Loading branch information
zaigie committed Mar 14, 2024
1 parent 471f3ed commit a818ebc
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 37 deletions.
37 changes: 1 addition & 36 deletions cmd/pst-agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"os"
"os/signal"
"path/filepath"
"sort"
"strconv"
"syscall"
"time"
Expand Down Expand Up @@ -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)
Expand All @@ -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)
}
}
}
20 changes: 20 additions & 0 deletions internal/system/createtime_unix.go
Original file line number Diff line number Diff line change
@@ -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()
}
29 changes: 29 additions & 0 deletions internal/system/createtime_windows.go
Original file line number Diff line number Diff line change
@@ -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())
}
76 changes: 76 additions & 0 deletions internal/system/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}
11 changes: 11 additions & 0 deletions internal/task/task.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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()
}

Expand Down
2 changes: 1 addition & 1 deletion internal/tool/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -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, "/") {
Expand Down

0 comments on commit a818ebc

Please sign in to comment.