-
Notifications
You must be signed in to change notification settings - Fork 53
/
errors.go
61 lines (53 loc) · 1.03 KB
/
errors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package util
import (
"errors"
"sort"
"sync"
)
// MultiErrGroup
// Best effort to run all tasks, then combines all errors
type MultiErrGroup struct {
errMu sync.Mutex
errs []error
sync.WaitGroup
}
func (i *MultiErrGroup) Add(tasks int) {
i.WaitGroup.Add(tasks)
}
func (i *MultiErrGroup) Done() {
i.WaitGroup.Done()
}
func (i *MultiErrGroup) Wait() {
i.WaitGroup.Wait()
}
func (i *MultiErrGroup) AddError(err error) {
i.errMu.Lock()
defer i.errMu.Unlock()
i.errs = append(i.errs, err)
}
func (i *MultiErrGroup) Error() error {
if len(i.errs) == 0 {
return nil
}
duped := map[string]struct{}{}
resErr := []error{}
for _, err := range i.errs {
if _, ok := duped[err.Error()]; !ok {
duped[err.Error()] = struct{}{}
resErr = append(resErr, err)
}
}
sort.Slice(resErr, func(i, j int) bool {
return resErr[i].Error() < resErr[j].Error()
})
return errors.Join(resErr...)
}
func (i *MultiErrGroup) Go(fn func() error) {
i.Add(1)
go func() {
defer i.Done()
if err := fn(); err != nil {
i.AddError(err)
}
}()
}