github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/watchapi/watch.go (about) 1 package watchapi 2 3 import ( 4 "github.com/docker/swarmkit/api" 5 "github.com/docker/swarmkit/manager/state" 6 "github.com/docker/swarmkit/manager/state/store" 7 "google.golang.org/grpc/codes" 8 "google.golang.org/grpc/status" 9 ) 10 11 // Watch starts a stream that returns any changes to objects that match 12 // the specified selectors. When the stream begins, it immediately sends 13 // an empty message back to the client. It is important to wait for 14 // this message before taking any actions that depend on an established 15 // stream of changes for consistency. 16 func (s *Server) Watch(request *api.WatchRequest, stream api.Watch_WatchServer) error { 17 ctx := stream.Context() 18 19 s.mu.Lock() 20 pctx := s.pctx 21 s.mu.Unlock() 22 if pctx == nil { 23 return errNotRunning 24 } 25 26 watchArgs, err := api.ConvertWatchArgs(request.Entries) 27 if err != nil { 28 return status.Errorf(codes.InvalidArgument, "%s", err.Error()) 29 } 30 31 watchArgs = append(watchArgs, state.EventCommit{}) 32 watch, cancel, err := store.WatchFrom(s.store, request.ResumeFrom, watchArgs...) 33 if err != nil { 34 return err 35 } 36 defer cancel() 37 38 // TODO(aaronl): Send current version in this WatchMessage? 39 if err := stream.Send(&api.WatchMessage{}); err != nil { 40 return err 41 } 42 43 var events []*api.WatchMessage_Event 44 for { 45 select { 46 case <-ctx.Done(): 47 return ctx.Err() 48 case <-pctx.Done(): 49 return pctx.Err() 50 case event := <-watch: 51 if commitEvent, ok := event.(state.EventCommit); ok && len(events) > 0 { 52 if err := stream.Send(&api.WatchMessage{Events: events, Version: commitEvent.Version}); err != nil { 53 return err 54 } 55 events = nil 56 } else if eventMessage := api.WatchMessageEvent(event.(api.Event)); eventMessage != nil { 57 if !request.IncludeOldObject { 58 eventMessage.OldObject = nil 59 } 60 events = append(events, eventMessage) 61 } 62 } 63 } 64 }