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)
|
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)
|
||||||
|
|
||||||
|
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 count int
|
||||||
var err error
|
var firstErr error
|
||||||
|
|
||||||
wg.Add(1)
|
for res := range ch {
|
||||||
go func() {
|
if firstErr == nil && res.err != nil {
|
||||||
defer wg.Done()
|
firstErr = res.err
|
||||||
|
continue
|
||||||
var countErr error
|
|
||||||
if count, countErr = countQ.Count(ctx); countErr != nil {
|
|
||||||
mu.Lock()
|
|
||||||
if err == nil {
|
|
||||||
err = countErr
|
|
||||||
}
|
|
||||||
mu.Unlock()
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
|
|
||||||
wg.Add(1)
|
count = res.count
|
||||||
go func() {
|
}
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
if scanErr := scanQ.Scan(ctx); scanErr == nil {
|
if firstErr != nil {
|
||||||
mu.Lock()
|
return 0, firstErr
|
||||||
if err == nil {
|
}
|
||||||
err = scanErr
|
|
||||||
}
|
|
||||||
mu.Unlock()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
wg.Wait()
|
return count, nil
|
||||||
|
|
||||||
return count, err
|
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue
Block a user