-
Notifications
You must be signed in to change notification settings - Fork 48
/
manager.go
95 lines (86 loc) · 2.66 KB
/
manager.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
package circuit
import (
"errors"
"expvar"
"sync"
)
// CommandPropertiesConstructor is a generic function that can create command properties to configure a circuit by name
// It is safe to leave not configured properties their empty value.
type CommandPropertiesConstructor func(circuitName string) Config
// Manager manages circuits with unique names
type Manager struct {
// DefaultCircuitProperties is a list of Config constructors called, in reverse order,
// to append or modify configuration for your circuit.
DefaultCircuitProperties []CommandPropertiesConstructor
circuitMap map[string]*Circuit
// mu locks circuitMap, not DefaultCircuitProperties
mu sync.RWMutex
}
// AllCircuits returns every hystrix circuit tracked
func (h *Manager) AllCircuits() []*Circuit {
if h == nil {
return nil
}
h.mu.RLock()
defer h.mu.RUnlock()
ret := make([]*Circuit, 0, len(h.circuitMap))
for _, c := range h.circuitMap {
ret = append(ret, c)
}
return ret
}
// Var allows you to expose all your hystrix circuits on expvar
func (h *Manager) Var() expvar.Var {
return expvar.Func(func() interface{} {
h.mu.RLock()
defer h.mu.RUnlock()
ret := make(map[string]interface{})
for k, v := range h.circuitMap {
ev := expvarToVal(v.Var())
if ev != nil {
ret[k] = ev
}
}
return ret
})
}
// GetCircuit returns the circuit with a given name, or nil if the circuit does not exist. You should not call this
// in live code. Instead, store the circuit somewhere and use the circuit directly.
func (h *Manager) GetCircuit(name string) *Circuit {
if h == nil {
return nil
}
h.mu.RLock()
defer h.mu.RUnlock()
return h.circuitMap[name]
}
// MustCreateCircuit calls CreateCircuit, but panics if the circuit name already exists
func (h *Manager) MustCreateCircuit(name string, config ...Config) *Circuit {
c, err := h.CreateCircuit(name, config...)
if err != nil {
panic(err)
}
return c
}
// CreateCircuit creates a new circuit, or returns error if a circuit with that name already exists
func (h *Manager) CreateCircuit(name string, configs ...Config) (*Circuit, error) {
h.mu.Lock()
defer h.mu.Unlock()
if h.circuitMap == nil {
h.circuitMap = make(map[string]*Circuit, 5)
}
finalConfig := Config{}
for _, c := range configs {
finalConfig.Merge(c)
}
// Merge in reverse order so the most recently appending constructor is more important
for i := len(h.DefaultCircuitProperties) - 1; i >= 0; i-- {
finalConfig.Merge(h.DefaultCircuitProperties[i](name))
}
_, exists := h.circuitMap[name]
if exists {
return nil, errors.New("circuit with that name already exists")
}
h.circuitMap[name] = NewCircuitFromConfig(name, finalConfig)
return h.circuitMap[name], nil
}