@@ -16,7 +16,9 @@ package opensergo
16
16
17
17
import (
18
18
"os"
19
+ "reflect"
19
20
"sync"
21
+ "time"
20
22
21
23
"github.com/opensergo/opensergo-control-plane/pkg/controller"
22
24
"github.com/opensergo/opensergo-control-plane/pkg/model"
@@ -42,7 +44,8 @@ func NewControlPlane() (*ControlPlane, error) {
42
44
return nil , err
43
45
}
44
46
45
- cp .server = transport .NewServer (uint32 (10246 ), []model.SubscribeRequestHandler {cp .handleSubscribeRequest })
47
+ handlers := []model.SubscribeRequestHandler {cp .handleSubscribeRequest , cp .handleUnSubscribeRequest }
48
+ cp .server = transport .NewServer (uint32 (10246 ), handlers )
46
49
cp .operator = operator
47
50
48
51
hostname , herr := os .Hostname ()
@@ -61,6 +64,10 @@ func (c *ControlPlane) Start() error {
61
64
if err != nil {
62
65
return err
63
66
}
67
+
68
+ // start the delete-connection goroutine
69
+ c .delConn ()
70
+
64
71
// Run the transport server
65
72
err = c .server .Run ()
66
73
if err != nil {
@@ -105,7 +112,24 @@ func (c *ControlPlane) sendMessageToStream(stream model.OpenSergoTransportStream
105
112
})
106
113
}
107
114
115
+ func (c * ControlPlane ) sendAckToStream (stream model.OpenSergoTransportStream , ack string , status * trpb.Status , respId string ) error {
116
+ if stream == nil {
117
+ return nil
118
+ }
119
+ return stream .SendMsg (& trpb.SubscribeResponse {
120
+ Status : status ,
121
+ Ack : ack ,
122
+ ControlPlane : c .protoDesc ,
123
+ ResponseId : respId ,
124
+ })
125
+ }
126
+
108
127
func (c * ControlPlane ) handleSubscribeRequest (clientIdentifier model.ClientIdentifier , request * trpb.SubscribeRequest , stream model.OpenSergoTransportStream ) error {
128
+
129
+ if trpb .SubscribeOpType_SUBSCRIBE != request .OpType {
130
+ return nil
131
+ }
132
+
109
133
//var labels []model.LabelKV
110
134
//if request.Target.Labels != nil {
111
135
// for _, label := range request.Target.Labels {
@@ -157,3 +181,116 @@ func (c *ControlPlane) handleSubscribeRequest(clientIdentifier model.ClientIdent
157
181
}
158
182
return nil
159
183
}
184
+
185
+ func (c * ControlPlane ) handleUnSubscribeRequest (clientIdentifier model.ClientIdentifier , request * trpb.SubscribeRequest , stream model.OpenSergoTransportStream ) error {
186
+
187
+ if trpb .SubscribeOpType_UNSUBSCRIBE != request .OpType {
188
+ return nil
189
+ }
190
+
191
+ for _ , kind := range request .Target .Kinds {
192
+ namespacedApp := model.NamespacedApp {
193
+ Namespace : request .Target .Namespace ,
194
+ App : request .Target .App ,
195
+ }
196
+ err := c .server .ConnectionManager ().RemoveWithIdentifier (namespacedApp , kind , clientIdentifier )
197
+
198
+ if err != nil {
199
+ status := & trpb.Status {
200
+ // TODO: defined a new errorCode
201
+ Code : transport .RegisterWatcherError ,
202
+ Message : "Remove from watcher error" ,
203
+ Details : nil ,
204
+ }
205
+ err = c .sendMessageToStream (stream , request .Target .Namespace , request .Target .App , kind , nil , status , request .RequestId )
206
+ if err != nil {
207
+ // TODO: log here
208
+ }
209
+ continue
210
+ }
211
+
212
+ targetConnections , _ := c .server .ConnectionManager ().Get (request .Target .Namespace , request .Target .App , kind )
213
+ if len (targetConnections ) < 1 {
214
+ delSubscribeConnChan <- delSubscribeConnInfo {
215
+ stream : stream ,
216
+ request : request ,
217
+ namespaceApp : namespacedApp ,
218
+ kind : kind ,
219
+ }
220
+ } else {
221
+ existConnection := c .server .ConnectionManager ().ExistConnection (kind )
222
+ if ! existConnection {
223
+ delSubscribeConnChan <- delSubscribeConnInfo {
224
+ stream : stream ,
225
+ request : request ,
226
+ namespaceApp : model.NamespacedApp {},
227
+ kind : kind ,
228
+ }
229
+ }
230
+ }
231
+ }
232
+
233
+ return nil
234
+ }
235
+
236
+ var delSubscribeConnChan chan delSubscribeConnInfo
237
+
238
+ type delSubscribeConnInfo struct {
239
+ stream model.OpenSergoTransportStream
240
+ request * trpb.SubscribeRequest
241
+ namespaceApp model.NamespacedApp
242
+ kind string
243
+ }
244
+
245
+ func (c * ControlPlane ) delConn () {
246
+ go func () {
247
+ for ! c .server .IsStarted () {
248
+ time .Sleep (time .Duration (1 ) * time .Second )
249
+ }
250
+
251
+ currDelConnInfo := <- delSubscribeConnChan
252
+ namespaceApp := currDelConnInfo .namespaceApp
253
+ kind := currDelConnInfo .kind
254
+ request := currDelConnInfo .request
255
+ stream := currDelConnInfo .stream
256
+
257
+ // TODO make time of sleep is configurable
258
+ time .Sleep (time .Duration (5 ) * time .Second )
259
+ var err error
260
+
261
+ // RemoveSubscribeTarget from CRDWatcher
262
+ if ! reflect .DeepEqual (namespaceApp , model.NamespacedApp {}) {
263
+ targetConnections , _ := c .server .ConnectionManager ().Get (namespaceApp .Namespace , namespaceApp .App , kind )
264
+ if len (targetConnections ) < 1 {
265
+ if crdWatcher , existed := c .operator .GetWatcher (kind ); existed {
266
+ err = crdWatcher .RemoveSubscribeTarget (model.SubscribeTarget {
267
+ Namespace : namespaceApp .Namespace ,
268
+ AppName : namespaceApp .App ,
269
+ Kind : kind ,
270
+ })
271
+ }
272
+ }
273
+ }
274
+
275
+ // delete Connection and CRDWatch
276
+ existConnection := c .server .ConnectionManager ().ExistConnection (kind )
277
+ if ! existConnection {
278
+ c .operator .RemoveWatcher (model.SubscribeTarget {
279
+ Namespace : namespaceApp .Namespace ,
280
+ AppName : namespaceApp .App ,
281
+ Kind : kind ,
282
+ })
283
+ }
284
+
285
+ // send ackMessage
286
+ status := & trpb.Status {
287
+ Code : transport .Success ,
288
+ Message : "unSubscribe success" ,
289
+ Details : nil ,
290
+ }
291
+ err = c .sendAckToStream (stream , transport .ACKFlag , status , request .RequestId )
292
+ if err != nil {
293
+ // TODO: log here
294
+ }
295
+ }()
296
+ }
0 commit comments