@@ -16,9 +16,9 @@ package relay
16
16
17
17
import (
18
18
"context"
19
+ "fmt"
20
+ "time"
19
21
20
- "google.golang.org/grpc/codes"
21
- "google.golang.org/grpc/status"
22
22
criv1 "k8s.io/cri-api/pkg/apis/runtime/v1"
23
23
24
24
"github.com/intel/cri-resource-manager/pkg/dump"
@@ -188,8 +188,23 @@ func (r *relay) CheckpointContainer(ctx context.Context, req *criv1.CheckpointCo
188
188
return r .client .CheckpointContainer (ctx , req )
189
189
}
190
190
191
- func (r * relay ) GetContainerEvents (_ * criv1.GetEventsRequest , _ criv1.RuntimeService_GetContainerEventsServer ) error {
192
- return status .Errorf (codes .Unimplemented , "method GetContainerEvents not implemented" )
191
+ func (r * relay ) GetContainerEvents (req * criv1.GetEventsRequest , srv criv1.RuntimeService_GetContainerEventsServer ) error {
192
+ evtC := r .addEventServer (req )
193
+
194
+ if err := r .startEventRelay (req ); err != nil {
195
+ r .delEventServer (req )
196
+ return err
197
+ }
198
+
199
+ for evt := range evtC {
200
+ if err := srv .Send (evt ); err != nil {
201
+ r .Errorf ("failed to relay/send container event: %v" , err )
202
+ r .delEventServer (req )
203
+ return err
204
+ }
205
+ }
206
+
207
+ return nil
193
208
}
194
209
195
210
func (r * relay ) ListMetricDescriptors (ctx context.Context , req * criv1.ListMetricDescriptorsRequest ) (* criv1.ListMetricDescriptorsResponse , error ) {
@@ -206,3 +221,80 @@ func (r *relay) RuntimeConfig(ctx context.Context, req *criv1.RuntimeConfigReque
206
221
r .dump ("RuntimeConfig" , req )
207
222
return r .client .RuntimeConfig (ctx , req )
208
223
}
224
+
225
+ const (
226
+ eventRelayTimeout = 1 * time .Second
227
+ )
228
+
229
+ func (r * relay ) addEventServer (req * criv1.GetEventsRequest ) chan * criv1.ContainerEventResponse {
230
+ r .Lock ()
231
+ defer r .Unlock ()
232
+
233
+ evtC := make (chan * criv1.ContainerEventResponse , 128 )
234
+ r .evtChans [req ] = evtC
235
+
236
+ return evtC
237
+ }
238
+
239
+ func (r * relay ) delEventServer (req * criv1.GetEventsRequest ) chan * criv1.ContainerEventResponse {
240
+ r .Lock ()
241
+ defer r .Unlock ()
242
+
243
+ evtC := r .evtChans [req ]
244
+ delete (r .evtChans , req )
245
+
246
+ return evtC
247
+ }
248
+
249
+ func (r * relay ) startEventRelay (req * criv1.GetEventsRequest ) error {
250
+ r .Lock ()
251
+ defer r .Unlock ()
252
+
253
+ if r .evtClient != nil {
254
+ return nil
255
+ }
256
+
257
+ c , err := r .client .GetContainerEvents (context .Background (), req )
258
+ if err != nil {
259
+ return fmt .Errorf ("failed to create container event client: %w" , err )
260
+ }
261
+
262
+ r .evtClient = c
263
+ go r .relayEvents ()
264
+
265
+ return nil
266
+ }
267
+
268
+ func (r * relay ) relayEvents () {
269
+ for {
270
+ evt , err := r .evtClient .Recv ()
271
+ if err != nil {
272
+ r .Errorf ("failed to relay/receive container event: %v" , err )
273
+ }
274
+
275
+ r .Lock ()
276
+
277
+ if err != nil {
278
+ for req , evtC := range r .evtChans {
279
+ delete (r .evtChans , req )
280
+ close (evtC )
281
+ }
282
+ r .evtClient = nil
283
+ } else {
284
+ for req , evtC := range r .evtChans {
285
+ select {
286
+ case evtC <- evt :
287
+ case _ = <- time .After (eventRelayTimeout ):
288
+ delete (r .evtChans , req )
289
+ close (evtC )
290
+ }
291
+ }
292
+ }
293
+
294
+ r .Unlock ()
295
+
296
+ if err != nil {
297
+ return
298
+ }
299
+ }
300
+ }
0 commit comments