refactor: scanAndCount - use channel to synchronize data with the main goroutine
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Dawid Wysokiński 2022-12-24 09:10:04 +01:00
parent f636d6ac94
commit def3161957
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892

View File

@ -46,44 +46,60 @@ func sortDirectionToString(sd domain.SortDirection) (string, error) {
return "", fmt.Errorf("%w: %d", domain.ErrUnsupportedSortDirection, sd) return "", fmt.Errorf("%w: %d", domain.ErrUnsupportedSortDirection, sd)
} }
type scanAndCountResult struct {
count int
err error
}
func scanAndCount( func scanAndCount(
ctx context.Context, ctx context.Context,
countQ *bun.SelectQuery, countQ *bun.SelectQuery,
scanQ *bun.SelectQuery, scanQ *bun.SelectQuery,
) (int, error) { ) (int, error) {
var wg sync.WaitGroup var wg sync.WaitGroup
var mu sync.Mutex ch := make(chan scanAndCountResult)
var count int
var err error
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
var countErr error count, err := countQ.Count(ctx)
if count, countErr = countQ.Count(ctx); countErr != nil { if err != nil {
mu.Lock() ch <- scanAndCountResult{err: err}
if err == nil { return
err = countErr
}
mu.Unlock()
} }
ch <- scanAndCountResult{count: count}
}() }()
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
if scanErr := scanQ.Scan(ctx); scanErr == nil { if err := scanQ.Scan(ctx); err != nil {
mu.Lock() ch <- scanAndCountResult{err: err}
if err == nil {
err = scanErr
}
mu.Unlock()
} }
}() }()
go func() {
wg.Wait() wg.Wait()
close(ch)
}()
return count, err var count int
var firstErr error
for res := range ch {
if firstErr == nil && res.err != nil {
firstErr = res.err
continue
}
count = res.count
}
if firstErr != nil {
return 0, firstErr
}
return count, nil
} }