From c6311c466f704ca4a7d0dbfc64f475487fd347d8 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 22 Sep 2024 15:39:36 +0800 Subject: [PATCH] :zap: Optimize merge files --- pkg/internal/services/merger.go | 52 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/pkg/internal/services/merger.go b/pkg/internal/services/merger.go index 1de36b7..34e50b9 100644 --- a/pkg/internal/services/merger.go +++ b/pkg/internal/services/merger.go @@ -2,22 +2,23 @@ package services import ( "fmt" - "git.solsynth.dev/hydrogen/paperclip/pkg/internal/database" - "git.solsynth.dev/hydrogen/paperclip/pkg/internal/models" - jsoniter "github.com/json-iterator/go" - "github.com/spf13/viper" "io" "os" "path/filepath" + + "git.solsynth.dev/hydrogen/paperclip/pkg/internal/database" + "git.solsynth.dev/hydrogen/paperclip/pkg/internal/models" + "github.com/spf13/viper" ) func MergeFileChunks(meta models.Attachment, arrange []string) (models.Attachment, error) { - destMap := viper.GetStringMap("destinations.temporary") + // Fetch destination from config + destMap := viper.GetStringMapString("destinations.temporary") var dest models.LocalDestination - rawDest, _ := jsoniter.Marshal(destMap) - _ = jsoniter.Unmarshal(rawDest, &dest) + dest.Path = destMap["path"] + // Create the destination file destPath := filepath.Join(dest.Path, meta.Uuid) destFile, err := os.Create(destPath) if err != nil { @@ -25,7 +26,10 @@ func MergeFileChunks(meta models.Attachment, arrange []string) (models.Attachmen } defer destFile.Close() - // Merge files + // 32KB buffer + buf := make([]byte, 32*1024) + + // Merge the chunks into the destination file for _, chunk := range arrange { chunkPath := filepath.Join(dest.Path, fmt.Sprintf("%s.part%s", meta.Uuid, chunk)) chunkFile, err := os.Open(chunkPath) @@ -33,27 +37,39 @@ func MergeFileChunks(meta models.Attachment, arrange []string) (models.Attachmen return meta, err } - _, err = io.Copy(destFile, chunkFile) - if err != nil { - _ = chunkFile.Close() - return meta, err - } + defer chunkFile.Close() // Ensure the file is closed after reading - _ = chunkFile.Close() + for { + n, err := chunkFile.Read(buf) + if err != nil && err != io.EOF { + return meta, err + } + if n == 0 { + break + } + + if _, err := destFile.Write(buf[:n]); err != nil { + return meta, err + } + } } - // Do post-upload tasks + // Post-upload tasks meta.IsUploaded = true meta.FileChunks = nil - database.C.Save(&meta) + if err := database.C.Save(&meta).Error; err != nil { + return meta, err + } CacheAttachment(meta) PublishAnalyzeTask(meta) - // Clean up + // Clean up: remove chunk files for _, chunk := range arrange { chunkPath := filepath.Join(dest.Path, fmt.Sprintf("%s.part%s", meta.Uuid, chunk)) - _ = os.Remove(chunkPath) + if err := os.Remove(chunkPath); err != nil { + return meta, err + } } return meta, nil