11
11
// See the License for the specific language governing permissions and
12
12
// limitations under the License.
13
13
14
- package maintainer
14
+ package bootstrap
15
15
16
16
import (
17
17
"time"
18
18
19
- "github.com/flowbehappy/tigate/heartbeatpb"
20
19
"github.com/flowbehappy/tigate/pkg/messaging"
21
20
"github.com/flowbehappy/tigate/pkg/node"
22
21
"github.com/flowbehappy/tigate/scheduler"
@@ -28,13 +27,13 @@ import (
28
27
// when a maintainer is started, it must wait of node to reported their managed dispatchers
29
28
// only all dispatcher has reported its status, maintainer can schedule tables
30
29
// maintainer collects all working dispatchers and
31
- type Bootstrapper struct {
32
- // changefeedID is the log identifier
33
- changefeedID string
30
+ type Bootstrapper [ T any ] struct {
31
+ // id is the log identifier
32
+ id string
34
33
// bootstrap identify is the bootstrapper is already bootstrapped
35
34
bootstrapped bool
36
35
37
- nodes map [node.ID ]* NodeStatus
36
+ nodes map [node.ID ]* NodeStatus [ T ]
38
37
newBootstrapMsg scheduler.NewBootstrapFn
39
38
40
39
// for ut test
@@ -43,10 +42,10 @@ type Bootstrapper struct {
43
42
}
44
43
45
44
// NewBootstrapper create a new bootstrap for a changefeed maintainer
46
- func NewBootstrapper ( cfID string , newBootstrapMsg scheduler.NewBootstrapFn ) * Bootstrapper {
47
- return & Bootstrapper {
48
- changefeedID : cfID ,
49
- nodes : make (map [node.ID ]* NodeStatus ),
45
+ func NewBootstrapper [ T any ]( id string , newBootstrapMsg scheduler.NewBootstrapFn ) * Bootstrapper [ T ] {
46
+ return & Bootstrapper [ T ] {
47
+ id : id ,
48
+ nodes : make (map [node.ID ]* NodeStatus [ T ] ),
50
49
bootstrapped : false ,
51
50
newBootstrapMsg : newBootstrapMsg ,
52
51
timeNowFunc : time .Now ,
@@ -55,13 +54,14 @@ func NewBootstrapper(cfID string, newBootstrapMsg scheduler.NewBootstrapFn) *Boo
55
54
}
56
55
57
56
// HandleBootstrapResponse cache the message reported remote node
58
- func (b * Bootstrapper ) HandleBootstrapResponse (
57
+ // return cached bootstrap response if all node are initialized
58
+ func (b * Bootstrapper [T ]) HandleBootstrapResponse (
59
59
from node.ID ,
60
- msg * heartbeatpb. MaintainerBootstrapResponse ) map [node.ID ]* heartbeatpb. MaintainerBootstrapResponse {
60
+ msg * T ) map [node.ID ]* T {
61
61
status , ok := b .nodes [from ]
62
62
if ! ok {
63
63
log .Warn ("node is not found, ignore" ,
64
- zap .String ("changefeed" , b .changefeedID ),
64
+ zap .String ("changefeed" , b .id ),
65
65
zap .Any ("from" , from ))
66
66
return nil
67
67
}
@@ -71,14 +71,14 @@ func (b *Bootstrapper) HandleBootstrapResponse(
71
71
}
72
72
73
73
// HandleNewNodes add node to bootstrapper and return rpc messages that need to be sent to remote node
74
- func (b * Bootstrapper ) HandleNewNodes (nodes []* node.Info ) []* messaging.TargetMessage {
74
+ func (b * Bootstrapper [ T ] ) HandleNewNodes (nodes []* node.Info ) []* messaging.TargetMessage {
75
75
msgs := make ([]* messaging.TargetMessage , 0 , len (nodes ))
76
76
for _ , info := range nodes {
77
77
if _ , ok := b .nodes [info .ID ]; ! ok {
78
78
// A new server.
79
- b .nodes [info .ID ] = NewNodeStatus (info )
79
+ b .nodes [info .ID ] = NewNodeStatus [ T ] (info )
80
80
log .Info ("find a new server" ,
81
- zap .String ("changefeed" , b .changefeedID ),
81
+ zap .String ("changefeed" , b .id ),
82
82
zap .String ("captureAddr" , info .AdvertiseAddr ),
83
83
zap .Any ("server" , info .ID ))
84
84
msgs = append (msgs , b .newBootstrapMsg (info .ID ))
@@ -91,26 +91,26 @@ func (b *Bootstrapper) HandleNewNodes(nodes []*node.Info) []*messaging.TargetMes
91
91
// HandleRemoveNodes remove node from bootstrapper,
92
92
// finished bootstrap if all node are initialized after these node removed
93
93
// return cached bootstrap
94
- func (b * Bootstrapper ) HandleRemoveNodes (nodeIDs []node.ID ) map [node.ID ]* heartbeatpb. MaintainerBootstrapResponse {
94
+ func (b * Bootstrapper [ T ] ) HandleRemoveNodes (nodeIDs []node.ID ) map [node.ID ]* T {
95
95
for _ , id := range nodeIDs {
96
96
status , ok := b .nodes [id ]
97
97
if ok {
98
98
delete (b .nodes , id )
99
99
log .Info ("remove node from bootstrap" ,
100
- zap .String ("changefeed" , b .changefeedID ),
100
+ zap .String ("changefeed" , b .id ),
101
101
zap .Int ("status" , int (status .state )),
102
102
zap .Any ("id" , id ))
103
103
} else {
104
104
log .Info ("node is node tracked by bootstrap" ,
105
- zap .String ("changefeed" , b .changefeedID ),
105
+ zap .String ("changefeed" , b .id ),
106
106
zap .Any ("id" , id ))
107
107
}
108
108
}
109
109
return b .fistBootstrap ()
110
110
}
111
111
112
112
// ResendBootstrapMessage return rpc message that need to be resent
113
- func (b * Bootstrapper ) ResendBootstrapMessage () []* messaging.TargetMessage {
113
+ func (b * Bootstrapper [ T ] ) ResendBootstrapMessage () []* messaging.TargetMessage {
114
114
var msgs []* messaging.TargetMessage
115
115
if ! b .CheckAllNodeInitialized () {
116
116
now := b .timeNowFunc ()
@@ -126,18 +126,18 @@ func (b *Bootstrapper) ResendBootstrapMessage() []*messaging.TargetMessage {
126
126
}
127
127
128
128
// GetAllNodes return all nodes the tracked by bootstrapper, the returned value must not be modified
129
- func (b * Bootstrapper ) GetAllNodes () map [node.ID ]* NodeStatus {
129
+ func (b * Bootstrapper [ T ] ) GetAllNodes () map [node.ID ]* NodeStatus [ T ] {
130
130
return b .nodes
131
131
}
132
132
133
133
// CheckAllNodeInitialized check if all server is initialized.
134
134
// returns true when all server reports the bootstrap response and bootstrapped
135
- func (b * Bootstrapper ) CheckAllNodeInitialized () bool {
135
+ func (b * Bootstrapper [ T ] ) CheckAllNodeInitialized () bool {
136
136
return b .bootstrapped && b .checkAllCaptureInitialized ()
137
137
}
138
138
139
139
// return true if all node reports the bootstrap response
140
- func (b * Bootstrapper ) checkAllCaptureInitialized () bool {
140
+ func (b * Bootstrapper [ T ] ) checkAllCaptureInitialized () bool {
141
141
for _ , captureStatus := range b .nodes {
142
142
// CaptureStateStopping is also considered initialized, because when
143
143
// a server shutdown, it becomes stopping, we need to move its tables
@@ -153,11 +153,11 @@ func (b *Bootstrapper) checkAllCaptureInitialized() bool {
153
153
// return nil is not bootstrapped or already bootstrapped before
154
154
// return cached heartbeatpb.MaintainerBootstrapResponse map if it's not bootstrapped before
155
155
// bootstrapper only return once
156
- func (b * Bootstrapper ) fistBootstrap () map [node.ID ]* heartbeatpb. MaintainerBootstrapResponse {
156
+ func (b * Bootstrapper [ T ] ) fistBootstrap () map [node.ID ]* T {
157
157
// first bootstrapped time, return the cached resp and clear it
158
158
if ! b .bootstrapped && b .checkAllCaptureInitialized () {
159
159
b .bootstrapped = true
160
- allCachedResp := make (map [node.ID ]* heartbeatpb. MaintainerBootstrapResponse , len (b .nodes ))
160
+ allCachedResp := make (map [node.ID ]* T , len (b .nodes ))
161
161
for _ , status := range b .nodes {
162
162
allCachedResp [status .node .ID ] = status .cachedBootstrapResp
163
163
// clear the cached data
@@ -178,17 +178,17 @@ const (
178
178
NodeStateInitialized NodeState = 2
179
179
)
180
180
181
- func NewNodeStatus (node * node.Info ) * NodeStatus {
182
- return & NodeStatus {
181
+ func NewNodeStatus [ T any ] (node * node.Info ) * NodeStatus [ T ] {
182
+ return & NodeStatus [ T ] {
183
183
state : NodeStateUninitialized ,
184
184
node : node ,
185
185
}
186
186
}
187
187
188
188
// NodeStatus identify the node the need be bootstrapped
189
- type NodeStatus struct {
189
+ type NodeStatus [ T any ] struct {
190
190
state NodeState
191
191
node * node.Info
192
- cachedBootstrapResp * heartbeatpb. MaintainerBootstrapResponse
192
+ cachedBootstrapResp * T
193
193
lastBootstrapTime time.Time
194
194
}
0 commit comments