refactor: scanAndCount - use channel to synchronize data with the main goroutine
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
f636d6ac94
commit
def3161957
|
@ -46,44 +46,60 @@ func sortDirectionToString(sd domain.SortDirection) (string, error) {
|
|||
return "", fmt.Errorf("%w: %d", domain.ErrUnsupportedSortDirection, sd)
|
||||
}
|
||||
|
||||
type scanAndCountResult struct {
|
||||
count int
|
||||
err error
|
||||
}
|
||||
|
||||
func scanAndCount(
|
||||
ctx context.Context,
|
||||
countQ *bun.SelectQuery,
|
||||
scanQ *bun.SelectQuery,
|
||||
) (int, error) {
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
ch := make(chan scanAndCountResult)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
count, err := countQ.Count(ctx)
|
||||
if err != nil {
|
||||
ch <- scanAndCountResult{err: err}
|
||||
return
|
||||
}
|
||||
ch <- scanAndCountResult{count: count}
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := scanQ.Scan(ctx); err != nil {
|
||||
ch <- scanAndCountResult{err: err}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
var count int
|
||||
var err error
|
||||
var firstErr error
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
var countErr error
|
||||
if count, countErr = countQ.Count(ctx); countErr != nil {
|
||||
mu.Lock()
|
||||
if err == nil {
|
||||
err = countErr
|
||||
}
|
||||
mu.Unlock()
|
||||
for res := range ch {
|
||||
if firstErr == nil && res.err != nil {
|
||||
firstErr = res.err
|
||||
continue
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
count = res.count
|
||||
}
|
||||
|
||||
if scanErr := scanQ.Scan(ctx); scanErr == nil {
|
||||
mu.Lock()
|
||||
if err == nil {
|
||||
err = scanErr
|
||||
}
|
||||
mu.Unlock()
|
||||
}
|
||||
}()
|
||||
if firstErr != nil {
|
||||
return 0, firstErr
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return count, err
|
||||
return count, nil
|
||||
}
|
||||
|
|
Reference in New Issue
Block a user