github.com/operator-framework/operator-lifecycle-manager@v0.30.0/pkg/lib/filemonitor/watcher.go (about)

     1  package filemonitor
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/fsnotify/fsnotify"
     7  	"github.com/sirupsen/logrus"
     8  )
     9  
    10  type watcher struct {
    11  	notify       *fsnotify.Watcher
    12  	pathsToWatch []string
    13  	logger       logrus.FieldLogger
    14  	onUpdateFn   func(logrus.FieldLogger, fsnotify.Event)
    15  }
    16  
    17  // NewWatch sets up monitoring on a slice of paths and will execute the update function to process each event
    18  func NewWatch(logger logrus.FieldLogger, pathsToWatch []string, onUpdateFn func(logrus.FieldLogger, fsnotify.Event)) (*watcher, error) {
    19  	notify, err := fsnotify.NewWatcher()
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	for _, item := range pathsToWatch {
    25  		// (non-recursive if a directory is added)
    26  		if err := notify.Add(item); err != nil {
    27  			return nil, err
    28  		}
    29  		logger.Debugf("monitoring path '%v'", item)
    30  	}
    31  
    32  	newWatcher := &watcher{
    33  		notify:       notify,
    34  		pathsToWatch: pathsToWatch,
    35  		onUpdateFn:   onUpdateFn,
    36  		logger:       logger,
    37  	}
    38  
    39  	return newWatcher, nil
    40  }
    41  
    42  func (w *watcher) Run(ctx context.Context) {
    43  	go func(ctx context.Context) {
    44  		for {
    45  			select {
    46  			case <-ctx.Done():
    47  				w.notify.Close() // always returns nil for the error
    48  				w.logger.Debug("terminating watcher")
    49  				return
    50  			case event := <-w.notify.Events:
    51  				w.logger.Debugf("watcher got event: %v", event)
    52  				if w.onUpdateFn != nil {
    53  					w.onUpdateFn(w.logger, event)
    54  				}
    55  			case err := <-w.notify.Errors:
    56  				w.logger.Warnf("watcher got error: %v", err)
    57  			}
    58  		}
    59  	}(ctx)
    60  }