-
Notifications
You must be signed in to change notification settings - Fork 1
/
breaker.go
79 lines (72 loc) · 1.59 KB
/
breaker.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
package circut
import (
"sync"
"sync/atomic"
"time"
)
//Breaker represents circut breaker
type Breaker struct {
prober Prober
Down int32
mux sync.RWMutex
resetTime time.Time
resetDuration time.Duration
initialResetDuration time.Duration
}
//IsUp returns true if resource is up
func (b *Breaker) IsUp() bool {
isUp := atomic.LoadInt32(&b.Down) == 0
if !isUp {
b.resetIfDue()
}
return isUp
}
//FlagUp flags resource down
func (b *Breaker) FlagUp() {
b.mux.Lock()
b.Down = 0
b.mux.Unlock()
b.resetDuration = b.initialResetDuration
}
//resetIfDue reset connection onDisconnect status if reset time is due,
func (b *Breaker) resetIfDue() {
b.mux.RLock()
dueTime := time.Now().After(b.resetTime)
b.mux.RUnlock()
if !dueTime {
return
}
b.mux.Lock()
dueTime = time.Now().After(b.resetTime)
if !dueTime {
b.mux.Unlock()
return
}
b.resetTime = time.Now().Add(b.resetDuration)
b.resetDuration = time.Duration(float32(b.resetDuration) * 1.5)
b.mux.Unlock()
go b.prober.Probe()
}
//FlagDown flags connection Down
func (b *Breaker) FlagDown() {
down := atomic.LoadInt32(&b.Down)
if down == 1 {
return
}
b.mux.Lock()
defer b.mux.Unlock()
if b.Down == 1 {
return
}
b.Down = 1
b.resetTime = time.Now().Add(b.resetDuration)
b.resetDuration *= 2 //double reset time each time service is Down
}
//New creates a new circut breaker
func New(resetDuration time.Duration, prober Prober) *Breaker {
return &Breaker{
prober: prober,
resetDuration: resetDuration,
initialResetDuration: resetDuration,
}
}