github.com/grahambrereton-form3/tilt@v0.10.18/internal/engine/docker_compose_event_watcher.go (about)

     1  package engine
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/pkg/errors"
     7  
     8  	"github.com/windmilleng/tilt/internal/dockercompose"
     9  	"github.com/windmilleng/tilt/internal/store"
    10  	"github.com/windmilleng/tilt/pkg/logger"
    11  )
    12  
    13  type DockerComposeEventWatcher struct {
    14  	watching bool
    15  	dcc      dockercompose.DockerComposeClient
    16  }
    17  
    18  func NewDockerComposeEventWatcher(dcc dockercompose.DockerComposeClient) *DockerComposeEventWatcher {
    19  	return &DockerComposeEventWatcher{
    20  		dcc: dcc,
    21  	}
    22  }
    23  
    24  func (w *DockerComposeEventWatcher) needsWatch(st store.RStore) bool {
    25  	state := st.RLockState()
    26  	defer st.RUnlockState()
    27  	return state.WatchFiles && !w.watching
    28  }
    29  
    30  func (w *DockerComposeEventWatcher) OnChange(ctx context.Context, st store.RStore) {
    31  	if !w.needsWatch(st) {
    32  		return
    33  	}
    34  
    35  	state := st.RLockState()
    36  	configPaths := state.DockerComposeConfigPath()
    37  	st.RUnlockState()
    38  
    39  	if len(configPaths) == 0 {
    40  		// No DC manifests to watch
    41  		return
    42  	}
    43  
    44  	w.watching = true
    45  	ch, err := w.startWatch(ctx, configPaths)
    46  	if err != nil {
    47  		err = errors.Wrap(err, "Subscribing to docker-compose events")
    48  		st.Dispatch(NewErrorAction(err))
    49  		return
    50  	}
    51  
    52  	go dispatchDockerComposeEventLoop(ctx, ch, st)
    53  }
    54  
    55  func (w *DockerComposeEventWatcher) startWatch(ctx context.Context, configPath []string) (<-chan string, error) {
    56  	return w.dcc.StreamEvents(ctx, configPath)
    57  }
    58  
    59  func dispatchDockerComposeEventLoop(ctx context.Context, ch <-chan string, st store.RStore) {
    60  	for {
    61  		select {
    62  		case evtJson, ok := <-ch:
    63  			if !ok {
    64  				return
    65  			}
    66  			evt, err := dockercompose.EventFromJsonStr(evtJson)
    67  			if err != nil {
    68  				// TODO(maia): handle this error better?
    69  				logger.Get(ctx).Infof("[DOCKER-COMPOSE WATCHER] failed to unmarshal dc event '%s' with err: %v", evtJson, err)
    70  				continue
    71  			}
    72  
    73  			st.Dispatch(DockerComposeEventAction{evt})
    74  		case <-ctx.Done():
    75  			return
    76  		}
    77  	}
    78  }