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  }