-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathasync.go
81 lines (72 loc) · 1.37 KB
/
async.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package async
import (
"errors"
"sync"
"time"
)
// Errors
var (
ErrTimeout = errors.New("operation timeout")
)
// ch := make(chan error)
// async.New(op1, op2).Run(ch)
//
// for {
// select {
// case err := <-errChan:
// if err != nil {
// // handle error and...abort?
// }
// // operations complete
// }
// }
// Ops is a list of operations. You should not need to use this type.
type Ops struct {
ops []func() error
}
// New accepts a list of operations to be run
func New(fns ...func() error) *Ops {
aops := Ops{}
aops.ops = fns
return &aops
}
// Add operation to be run
func (a *Ops) Add(fn func() error) {
a.ops = append(a.ops, fn)
}
// Run executes the operation list within a go routine
func (a *Ops) Run(ch chan error) {
go func() {
var wg sync.WaitGroup
wg.Add(len(a.ops))
for _, op := range a.ops {
go func(op func() error) {
if err := op(); err != nil {
ch <- err
return
}
wg.Done()
}(op)
}
wg.Wait()
ch <- nil
}()
}
// RunWithTimeout runs the operations and returns an ErrTimeout if the operations
// are not completed before the specified timeout duration.
func (a *Ops) RunWithTimeout(ch chan error, d time.Duration) {
tch := make(chan error)
a.Run(tch)
go func() {
for {
select {
case err := <-tch:
ch <- err
return
case <-time.Tick(d):
ch <- ErrTimeout
return
}
}
}()
}