-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path19_brdm4.go
122 lines (114 loc) · 2.27 KB
/
19_brdm4.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"fmt"
"math/rand"
"time"
)
var steps = [4]string{
"deployBroserv",
"deployBroapp",
"deployBromon",
"deployPAS",
}
var closing chan chan error
func First(channels ...chan string) chan string {
ch := make(chan string)
for _, c := range channels {
go func(c chan string) {
select {
case v := <-c:
ch <- v
case <-time.After(500 * time.Millisecond):
return
}
}(c)
}
return ch
}
func runStep(stepName string, replica string) chan string {
ch := make(chan string)
go func() {
duration := time.Duration(rand.Intn(1000)) * time.Millisecond
time.Sleep(duration)
fmt.Println("stepName: ", stepName, " elapsed: ", duration, "ms")
ch <- replica
}()
return ch
}
func runStepWithReplica(stepName string) chan string {
return First(
runStep(stepName, "r1"),
runStep(stepName, "r2"),
runStep(stepName, "r3"),
)
}
func runStepBlock() error {
fmt.Println("===============RUNNING STEPBLOCK=============")
c := make([]chan string, 4)
now := time.Now()
for i, v := range steps {
c[i] = runStepWithReplica(v)
}
done := 0
ch := make(chan string)
for i := 0; i < 4; i++ {
go func(stepName string, c chan string) {
select {
case r := <-c:
ch <- r
case <-time.After(500 * time.Millisecond):
ch <- "timeout"
return
}
}(steps[i], c[i])
}
for i := 0; i < 4; i++ {
replica := <-ch
if replica != "timeout" {
fmt.Println(steps[i], " is done with replica ", replica)
}
}
elapsed := time.Now().Sub(now)
fmt.Println("total: ", elapsed)
fmt.Printf("%d jobs done before timeout\n", done)
fmt.Println("=======================DONE==================")
return fmt.Errorf("some error happened")
}
func Close() error {
errc := make(chan error)
closing <- errc
return <-errc
}
func main() {
req := make(chan bool)
closing = make(chan chan error)
go func() {
<-time.After(5 * time.Second)
err := Close()
if err != nil {
fmt.Println("Error happened!?")
fmt.Println(err)
}
}()
go func(r chan bool) {
for {
r <- true
time.Sleep(1 * time.Second)
}
}(req)
var err error
err = nil
timeout := time.After(10 * time.Second)
for {
select {
case <-req:
err = runStepBlock()
case errc := <-closing:
req = nil
errc <- err
case <-timeout:
fmt.Println("shutting down...")
return
}
}
}