-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnode_router.go
77 lines (64 loc) · 1.89 KB
/
node_router.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
package main
import (
"errors"
"math/rand"
"time"
)
// Router to nodes
type NodeRouter struct {
}
// Pick node
func (this *NodeRouter) PickNode(criteria *NodeRouterCriteria) (string, error) {
nodesMap := gossip.GetNodeStates()
inputNodes := make([]*GossipNodeState, 0)
for _, ns := range nodesMap {
inputNodes = append(inputNodes, ns)
}
nodeCount := len(inputNodes)
// No nodes? Add route to localhost
if nodeCount == 0 {
inputNodes = append(inputNodes, gossip.GetNodeState(runtime.GetNode()))
}
// Apply criteria
tmp := make([]*GossipNodeState, 0)
for _, inputNode := range inputNodes {
// Recent gossipped only
ts := unixTsUint32()
minTs := ts - 60
if inputNode.GetLastHelloReceived() < minTs || inputNode.GetLastHelloSent() < minTs {
log.Warnf("Ignoring node %s for last gossip (now %d, min ts %d, received %d, sent %d)", inputNode.Node, ts, minTs, inputNode.GetLastHelloReceived(), inputNode.GetLastHelloSent())
continue
}
// Local route?
if criteria != nil && criteria.ExcludeLocalNodes {
if inputNode.Node == runtime.GetNode() || inputNode.Node == "localhost" || inputNode.Node == "127.0.0.1" {
continue
}
}
tmp = append(tmp, inputNode)
}
inputNodes = tmp
// Anything left after filtering?
if len(inputNodes) < 1 {
return "", errors.New("Unable to pick node from router")
}
// Randomize nodes
nodes := shuffleGossipNodeStates(inputNodes)
// Return first node (after shuffling above)
// @todo smarter node selection, e.g. https://labs.spotify.com/2015/12/08/els-part-1/
return nodes[0].Node, nil
}
// New router
func newNodeRouter() *NodeRouter {
return &NodeRouter{}
}
// Randomize order
func shuffleGossipNodeStates(arr []*GossipNodeState) []*GossipNodeState {
t := time.Now()
rand.Seed(int64(t.Nanosecond())) // no shuffling without this line
for i := len(arr) - 1; i > 0; i-- {
j := rand.Intn(i)
arr[i], arr[j] = arr[j], arr[i]
}
return arr
}