18 | 18 |
func TestBreakerErrorExpiry(t *testing.T) {
|
19 | 19 |
breaker := New(2, 1, 1*time.Second)
|
20 | 20 |
|
21 | |
for i := 0; i < 5; i++ {
|
|
21 |
for i := 0; i < 3; i++ {
|
22 | 22 |
if err := breaker.Run(returnsError); err != errSomeError {
|
|
23 |
t.Error(err)
|
|
24 |
}
|
|
25 |
time.Sleep(1 * time.Second)
|
|
26 |
}
|
|
27 |
|
|
28 |
for i := 0; i < 3; i++ {
|
|
29 |
if err := breaker.Go(returnsError); err != nil {
|
23 | 30 |
t.Error(err)
|
24 | 31 |
}
|
25 | 32 |
time.Sleep(1 * time.Second)
|
|
76 | 83 |
}
|
77 | 84 |
}
|
78 | 85 |
|
|
86 |
func TestBreakerAsyncStateTransitions(t *testing.T) {
|
|
87 |
breaker := New(3, 2, 1*time.Second)
|
|
88 |
|
|
89 |
// three errors opens the breaker
|
|
90 |
for i := 0; i < 3; i++ {
|
|
91 |
if err := breaker.Go(returnsError); err != nil {
|
|
92 |
t.Error(err)
|
|
93 |
}
|
|
94 |
}
|
|
95 |
|
|
96 |
// just enough to yield the scheduler and let the goroutines work off
|
|
97 |
time.Sleep(1 * time.Millisecond)
|
|
98 |
|
|
99 |
// breaker is open
|
|
100 |
for i := 0; i < 5; i++ {
|
|
101 |
if err := breaker.Go(returnsError); err != ErrBreakerOpen {
|
|
102 |
t.Error(err)
|
|
103 |
}
|
|
104 |
}
|
|
105 |
|
|
106 |
// wait for it to half-close
|
|
107 |
time.Sleep(2 * time.Second)
|
|
108 |
// one success works, but is not enough to fully close
|
|
109 |
if err := breaker.Go(returnsSuccess); err != nil {
|
|
110 |
t.Error(err)
|
|
111 |
}
|
|
112 |
// error works, but re-opens immediately
|
|
113 |
if err := breaker.Go(returnsError); err != nil {
|
|
114 |
t.Error(err)
|
|
115 |
}
|
|
116 |
// just enough to yield the scheduler and let the goroutines work off
|
|
117 |
time.Sleep(1 * time.Millisecond)
|
|
118 |
// breaker is open
|
|
119 |
if err := breaker.Go(returnsError); err != ErrBreakerOpen {
|
|
120 |
t.Error(err)
|
|
121 |
}
|
|
122 |
|
|
123 |
// wait for it to half-close
|
|
124 |
time.Sleep(2 * time.Second)
|
|
125 |
// two successes is enough to close it for good
|
|
126 |
for i := 0; i < 2; i++ {
|
|
127 |
if err := breaker.Go(returnsSuccess); err != nil {
|
|
128 |
t.Error(err)
|
|
129 |
}
|
|
130 |
}
|
|
131 |
// just enough to yield the scheduler and let the goroutines work off
|
|
132 |
time.Sleep(1 * time.Millisecond)
|
|
133 |
// error works
|
|
134 |
if err := breaker.Go(returnsError); err != nil {
|
|
135 |
t.Error(err)
|
|
136 |
}
|
|
137 |
// just enough to yield the scheduler and let the goroutines work off
|
|
138 |
time.Sleep(1 * time.Millisecond)
|
|
139 |
// breaker is still closed
|
|
140 |
if err := breaker.Go(returnsSuccess); err != nil {
|
|
141 |
t.Error(err)
|
|
142 |
}
|
|
143 |
}
|
|
144 |
|
79 | 145 |
func ExampleBreaker() {
|
80 | 146 |
breaker := New(3, 1, 5*time.Second)
|
81 | 147 |
|