perf: improve error handling by having error channel

This commit is contained in:
Antoine Aflalo
2024-08-27 09:54:47 -04:00
parent 1ac8b42cf5
commit bc52b1a949
2 changed files with 31 additions and 10 deletions

View File

@@ -83,6 +83,8 @@ func ConvertCbzCommand(cmd *cobra.Command, args []string) error {
} }
// Channel to manage the files to process // Channel to manage the files to process
fileChan := make(chan string) fileChan := make(chan string)
// Channel to collect errors
errorChan := make(chan error, parallelism)
// WaitGroup to wait for all goroutines to finish // WaitGroup to wait for all goroutines to finish
var wg sync.WaitGroup var wg sync.WaitGroup
@@ -98,7 +100,7 @@ func ConvertCbzCommand(cmd *cobra.Command, args []string) error {
// Load the chapter // Load the chapter
chapter, err := cbz.LoadChapter(path) chapter, err := cbz.LoadChapter(path)
if err != nil { if err != nil {
fmt.Printf("Failed to load chapter: %v\n", err) errorChan <- fmt.Errorf("failed to load chapter: %v", err)
continue continue
} }
@@ -112,7 +114,7 @@ func ConvertCbzCommand(cmd *cobra.Command, args []string) error {
fmt.Println(msg) fmt.Println(msg)
}) })
if err != nil { if err != nil {
fmt.Printf("Failed to convert chapter: %v\n", err) errorChan <- fmt.Errorf("failed to convert chapter: %v", err)
continue continue
} }
convertedChapter.SetConverted() convertedChapter.SetConverted()
@@ -124,7 +126,7 @@ func ConvertCbzCommand(cmd *cobra.Command, args []string) error {
} }
err = cbz.WriteChapterToCBZ(convertedChapter, outputPath) err = cbz.WriteChapterToCBZ(convertedChapter, outputPath)
if err != nil { if err != nil {
fmt.Printf("Failed to write converted chapter: %v\n", err) errorChan <- fmt.Errorf("failed to write converted chapter: %v", err)
continue continue
} }
@@ -150,8 +152,18 @@ func ConvertCbzCommand(cmd *cobra.Command, args []string) error {
return fmt.Errorf("error walking the path: %w", err) return fmt.Errorf("error walking the path: %w", err)
} }
close(fileChan) // Close the channel to signal workers to stop close(fileChan) // Close the channel to signal workers to stop
wg.Wait() // Wait for all workers to finish wg.Wait() // Wait for all workers to finish
close(errorChan) // Close the error channel
var errs []error
for err := range errorChan {
errs = append(errs, err)
}
if len(errs) > 0 {
return fmt.Errorf("encountered errors: %v", errs)
}
return nil return nil
} }

View File

@@ -12,7 +12,6 @@ import (
_ "image/jpeg" _ "image/jpeg"
"image/png" "image/png"
"io" "io"
"log"
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
@@ -59,6 +58,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
maxGoroutines := runtime.NumCPU() maxGoroutines := runtime.NumCPU()
pagesChan := make(chan *packer2.PageContainer, maxGoroutines) pagesChan := make(chan *packer2.PageContainer, maxGoroutines)
errChan := make(chan error, maxGoroutines)
var wgPages sync.WaitGroup var wgPages sync.WaitGroup
wgPages.Add(len(chapter.Pages)) wgPages.Add(len(chapter.Pages))
@@ -78,6 +78,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
buffer := new(bytes.Buffer) buffer := new(bytes.Buffer)
err := png.Encode(buffer, convertedPage.Image) err := png.Encode(buffer, convertedPage.Image)
if err != nil { if err != nil {
errChan <- err
<-guard <-guard
return return
} }
@@ -91,7 +92,6 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
pagesMutex.Unlock() pagesMutex.Unlock()
<-guard <-guard
}(page) }(page)
} }
}() }()
@@ -101,7 +101,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
splitNeeded, img, format, err := converter.checkPageNeedsSplit(page) splitNeeded, img, format, err := converter.checkPageNeedsSplit(page)
if err != nil { if err != nil {
log.Fatalf("error checking if page %d d of chapter %s needs split: %v", page.Index, chapter.FilePath, err) errChan <- fmt.Errorf("error checking if page %d of chapter %s needs split: %v", page.Index, chapter.FilePath, err)
return return
} }
@@ -112,7 +112,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
} }
images, err := converter.cropImage(img) images, err := converter.cropImage(img)
if err != nil { if err != nil {
log.Fatalf("error converting page %d of chapter %s to webp: %v", page.Index, chapter.FilePath, err) errChan <- fmt.Errorf("error converting page %d of chapter %s to webp: %v", page.Index, chapter.FilePath, err)
return return
} }
@@ -123,12 +123,21 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
pagesChan <- packer2.NewContainer(page, img, "N/A") pagesChan <- packer2.NewContainer(page, img, "N/A")
} }
}(page) }(page)
} }
wgPages.Wait() wgPages.Wait()
wgConvertedPages.Wait() wgConvertedPages.Wait()
close(pagesChan) close(pagesChan)
close(errChan)
var errList []error
for err := range errChan {
errList = append(errList, err)
}
if len(errList) > 0 {
return nil, fmt.Errorf("encountered errors: %v", errList)
}
slices.SortFunc(pages, func(a, b *packer2.Page) int { slices.SortFunc(pages, func(a, b *packer2.Page) int {
if a.Index == b.Index { if a.Index == b.Index {