(Feat): New feature added: batch operations

This commit is contained in:
2025-11-21 08:28:35 +00:00
parent 21b59c759e
commit 2929bf1613

191
internal/archiver/batch.go Normal file
View File

@@ -0,0 +1,191 @@
package archiver
import (
"fmt"
"sync"
"zipprine/internal/models"
)
// BatchCompressConfig holds configuration for batch compression operations
type BatchCompressConfig struct {
Configs []*models.CompressConfig
Parallel bool
MaxWorkers int
OnProgress func(index int, total int, filename string)
OnError func(index int, filename string, err error)
OnComplete func(index int, filename string)
}
// BatchCompress compresses multiple sources in batch
func BatchCompress(batchConfig *BatchCompressConfig) []error {
if batchConfig.MaxWorkers <= 0 {
batchConfig.MaxWorkers = 4
}
errors := make([]error, len(batchConfig.Configs))
if !batchConfig.Parallel {
// Sequential processing
for i, config := range batchConfig.Configs {
if batchConfig.OnProgress != nil {
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.OutputPath)
}
err := Compress(config)
errors[i] = err
if err != nil && batchConfig.OnError != nil {
batchConfig.OnError(i, config.OutputPath, err)
} else if batchConfig.OnComplete != nil {
batchConfig.OnComplete(i, config.OutputPath)
}
}
return errors
}
// Parallel processing with worker pool
var wg sync.WaitGroup
jobs := make(chan int, len(batchConfig.Configs))
// Start workers
for w := 0; w < batchConfig.MaxWorkers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for i := range jobs {
config := batchConfig.Configs[i]
if batchConfig.OnProgress != nil {
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.OutputPath)
}
err := Compress(config)
errors[i] = err
if err != nil && batchConfig.OnError != nil {
batchConfig.OnError(i, config.OutputPath, err)
} else if batchConfig.OnComplete != nil {
batchConfig.OnComplete(i, config.OutputPath)
}
}
}()
}
// Send jobs
for i := range batchConfig.Configs {
jobs <- i
}
close(jobs)
wg.Wait()
return errors
}
// BatchExtractConfig holds configuration for batch extraction operations
type BatchExtractConfig struct {
Configs []*models.ExtractConfig
Parallel bool
MaxWorkers int
OnProgress func(index int, total int, filename string)
OnError func(index int, filename string, err error)
OnComplete func(index int, filename string)
}
// BatchExtract extracts multiple archives in batch
func BatchExtract(batchConfig *BatchExtractConfig) []error {
if batchConfig.MaxWorkers <= 0 {
batchConfig.MaxWorkers = 4
}
errors := make([]error, len(batchConfig.Configs))
if !batchConfig.Parallel {
// Sequential processing
for i, config := range batchConfig.Configs {
if batchConfig.OnProgress != nil {
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.ArchivePath)
}
err := Extract(config)
errors[i] = err
if err != nil && batchConfig.OnError != nil {
batchConfig.OnError(i, config.ArchivePath, err)
} else if batchConfig.OnComplete != nil {
batchConfig.OnComplete(i, config.ArchivePath)
}
}
return errors
}
// Parallel processing with worker pool
var wg sync.WaitGroup
jobs := make(chan int, len(batchConfig.Configs))
// Start workers
for w := 0; w < batchConfig.MaxWorkers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for i := range jobs {
config := batchConfig.Configs[i]
if batchConfig.OnProgress != nil {
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.ArchivePath)
}
err := Extract(config)
errors[i] = err
if err != nil && batchConfig.OnError != nil {
batchConfig.OnError(i, config.ArchivePath, err)
} else if batchConfig.OnComplete != nil {
batchConfig.OnComplete(i, config.ArchivePath)
}
}
}()
}
// Send jobs
for i := range batchConfig.Configs {
jobs <- i
}
close(jobs)
wg.Wait()
return errors
}
// ConvertArchive converts an archive from one format to another
func ConvertArchive(sourcePath, destPath string, sourceType, destType models.ArchiveType) error {
// Create temporary directory for extraction
tmpDir := destPath + ".tmp"
// Extract source archive
extractConfig := &models.ExtractConfig{
ArchivePath: sourcePath,
DestPath: tmpDir,
ArchiveType: sourceType,
OverwriteAll: true,
PreservePerms: true,
}
if err := Extract(extractConfig); err != nil {
return fmt.Errorf("failed to extract source archive: %w", err)
}
// Compress to destination format
compressConfig := &models.CompressConfig{
SourcePath: tmpDir,
OutputPath: destPath,
ArchiveType: destType,
CompressionLevel: 5,
}
if err := Compress(compressConfig); err != nil {
return fmt.Errorf("failed to create destination archive: %w", err)
}
return nil
}