-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathselector.go
84 lines (71 loc) · 1.65 KB
/
selector.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
package zk
import (
"math/rand"
"sync"
)
// SelectNextOutput ...
type SelectNextOutput struct {
Server string
RetryStart bool // equal to true if the client should sleep after retry to the next server
}
// ServerSelector for selecting servers for connecting
type ServerSelector interface {
// Init the selector
Init(servers []string)
// Next choose the next server for connecting
Next() SelectNextOutput
// NotifyConnected notify the selector for retrying the same address later after successfully connected
NotifyConnected()
}
// ServerListSelector ...
type ServerListSelector struct {
mut sync.Mutex
servers []string
lastIndex int
numNextCalls int
rand *rand.Rand
notified bool
}
// NewServerListSelector ...
func NewServerListSelector(seed int64) ServerSelector {
return &ServerListSelector{
rand: rand.New(rand.NewSource(seed)),
}
}
// Init ...
func (s *ServerListSelector) Init(servers []string) {
s.mut.Lock()
defer s.mut.Unlock()
s.servers = FormatServers(servers)
stringShuffleRand(s.servers, s.rand)
s.lastIndex = -1
s.numNextCalls = 0
}
// Next ...
func (s *ServerListSelector) Next() SelectNextOutput {
s.mut.Lock()
defer s.mut.Unlock()
s.notified = false
s.lastIndex++
s.lastIndex = s.lastIndex % len(s.servers)
s.numNextCalls++
retryStart := false
if s.numNextCalls >= len(s.servers) {
retryStart = true
}
return SelectNextOutput{
Server: s.servers[s.lastIndex],
RetryStart: retryStart,
}
}
// NotifyConnected ...
func (s *ServerListSelector) NotifyConnected() {
s.mut.Lock()
defer s.mut.Unlock()
if s.notified {
return
}
s.lastIndex--
s.notified = true
s.numNextCalls = 0
}