@@ -16,9 +16,9 @@ package relay
1616
1717import (
1818 "context"
19+ "fmt"
20+ "time"
1921
20- "google.golang.org/grpc/codes"
21- "google.golang.org/grpc/status"
2222 criv1 "k8s.io/cri-api/pkg/apis/runtime/v1"
2323
2424 "github.com/intel/cri-resource-manager/pkg/dump"
@@ -188,8 +188,23 @@ func (r *relay) CheckpointContainer(ctx context.Context, req *criv1.CheckpointCo
188188 return r .client .CheckpointContainer (ctx , req )
189189}
190190
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
193208}
194209
195210func (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
206221 r .dump ("RuntimeConfig" , req )
207222 return r .client .RuntimeConfig (ctx , req )
208223}
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