1
1
package cluster
2
2
3
- import "time"
3
+ import (
4
+ "encoding/json"
5
+ "io/ioutil"
6
+ "logger"
7
+ "net/http"
8
+ "stash.cloudflare.com/go-stream/util/slog"
9
+ "time"
10
+ )
11
+
12
+ const (
13
+ MAX_ERAS_SAVED = 10
14
+ )
4
15
5
16
/* There should be a separate manager for each service */
6
17
type Manager interface {
@@ -23,3 +34,93 @@ func (c *StaticManager) GetCurrentEra() Era {
23
34
func NewStaticManager (e Era ) * StaticManager {
24
35
return & StaticManager {e }
25
36
}
37
+
38
+ type DynamicBBManager struct {
39
+ Eras map [time.Time ]Era
40
+ ErasAdded []time.Time
41
+ BBHosts []string
42
+ CurrentTime time.Time
43
+ }
44
+
45
+ type BBHost struct {
46
+ Disk_free float32
47
+ Load float32
48
+ Name string
49
+ Host string
50
+ Port string
51
+ }
52
+
53
+ type BBResult struct {
54
+ Nodes []BBHost
55
+ }
56
+
57
+ func (c * DynamicBBManager ) GetEra (t time.Time ) Era {
58
+ if ct , ok := c .Eras [t ]; ok {
59
+ return ct
60
+ }
61
+ return c .Eras [c .CurrentTime ]
62
+ }
63
+
64
+ func (c * DynamicBBManager ) GetCurrentEra () Era {
65
+ return c .Eras [c .CurrentTime ]
66
+ }
67
+
68
+ func (c * DynamicBBManager ) pullLatestEra () (err error ) {
69
+ for _ , url := range c .BBHosts {
70
+ if resp , err := http .Get (url ); err == nil {
71
+ if bbbody , err := ioutil .ReadAll (resp .Body ); err == nil {
72
+ // Try parsing this.
73
+ bbr := BBResult {}
74
+ if err := json .Unmarshal (bbbody , & bbr ); err == nil {
75
+ ctime := time .Now ()
76
+
77
+ we := NewWeightedEra ()
78
+ for _ , node := range bbr .Nodes {
79
+ n := NewWeightedNode (node .Name , node .Host , node .Port , node .Disk_free , node .Load )
80
+ slog .Logf (logger .Levels .Debug , "Trasport LOG INFO %v" , n )
81
+ we .Add (n )
82
+ }
83
+
84
+ // Once all the nodes are in for this era, re-weight the Era
85
+ we .NormalizeAndPopulateMap ()
86
+ c .Eras [ctime ] = we
87
+ c .CurrentTime = ctime
88
+ c .ErasAdded = append (c .ErasAdded , ctime )
89
+
90
+ // And Remove any super old eras
91
+ if len (c .ErasAdded ) > MAX_ERAS_SAVED {
92
+ delete (c .Eras , c .ErasAdded [0 ])
93
+ c .ErasAdded = append (c .ErasAdded [:1 ], c .ErasAdded [2 :]... )
94
+ }
95
+
96
+ // Once we have hit one BB server with no error, no need to try any others.
97
+ break
98
+ }
99
+ }
100
+ }
101
+ }
102
+ return
103
+ }
104
+
105
+ func (c * DynamicBBManager ) keepErasCurrent () {
106
+ for {
107
+ time .Sleep (60 * time .Second )
108
+ slog .Logf (logger .Levels .Debug , "Updating to new era" )
109
+ err := c .pullLatestEra ()
110
+ if err != nil {
111
+ slog .Logf (logger .Levels .Error , "Cannot get a valid era %v" , err )
112
+ }
113
+ }
114
+ }
115
+
116
+ func NewDynamicBBManager (bbHosts []string ) * DynamicBBManager {
117
+ dm := DynamicBBManager {make (map [time.Time ]Era ), make ([]time.Time , 0 , 0 ), bbHosts , time .Now ()}
118
+ err := dm .pullLatestEra ()
119
+ if err != nil || len (dm .Eras ) == 0 {
120
+ slog .Fatalf ("Cannot get a valid era %v" , err )
121
+ }
122
+
123
+ // Keep updating with periodic info
124
+ go dm .keepErasCurrent ()
125
+ return & dm
126
+ }
0 commit comments