github.com/Cloud-Foundations/Dominator@v0.3.4/lib/configwatch/impl.go (about)

     1  package configwatch
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"time"
     7  
     8  	"github.com/Cloud-Foundations/Dominator/lib/fsutil"
     9  	"github.com/Cloud-Foundations/Dominator/lib/log"
    10  	"github.com/Cloud-Foundations/Dominator/lib/url/urlutil"
    11  )
    12  
    13  func watch(url string, checkInterval time.Duration,
    14  	decoder Decoder, logger log.DebugLogger) (<-chan interface{}, error) {
    15  	rawChannel, err := urlutil.WatchUrl(url, checkInterval, logger)
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  	configChannel := make(chan interface{}, 1)
    20  	go watchLoop(rawChannel, configChannel, decoder, logger)
    21  	return configChannel, nil
    22  }
    23  
    24  func watchLoop(rawChannel <-chan io.ReadCloser,
    25  	configChannel chan<- interface{}, decoder Decoder, logger log.DebugLogger) {
    26  	var previousChecksum []byte
    27  	for reader := range rawChannel {
    28  		checksumReader := fsutil.NewChecksumReader(reader)
    29  		if config, err := decoder(checksumReader); err != nil {
    30  			logger.Println(err)
    31  		} else {
    32  			newChecksum := checksumReader.GetChecksum()
    33  			if bytes.Equal(newChecksum, previousChecksum) {
    34  				logger.Debugln(1, "ignoring unchanged configuration")
    35  			} else {
    36  				configChannel <- config
    37  				previousChecksum = newChecksum
    38  			}
    39  		}
    40  		reader.Close()
    41  	}
    42  	close(configChannel)
    43  }
    44  
    45  func watchWithCache(url string, checkInterval time.Duration,
    46  	decoder Decoder, cacheFilename string, initialTimeout time.Duration,
    47  	logger log.DebugLogger) (<-chan interface{}, error) {
    48  	rawChannel, err := urlutil.WatchUrlWithCache(url, checkInterval,
    49  		cacheFilename, initialTimeout, logger)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	configChannel := make(chan interface{}, 1)
    54  	go watchLoopWithCache(rawChannel, configChannel, decoder, logger)
    55  	return configChannel, nil
    56  }
    57  
    58  func watchLoopWithCache(rawChannel <-chan *urlutil.CachedReadCloser,
    59  	configChannel chan<- interface{}, decoder Decoder, logger log.DebugLogger) {
    60  	var previousChecksum []byte
    61  	for reader := range rawChannel {
    62  		checksumReader := fsutil.NewChecksumReader(reader)
    63  		if config, err := decoder(checksumReader); err != nil {
    64  			logger.Println(err)
    65  		} else {
    66  			newChecksum := checksumReader.GetChecksum()
    67  			if bytes.Equal(newChecksum, previousChecksum) {
    68  				logger.Debugln(1, "ignoring unchanged configuration")
    69  			} else {
    70  				if err := reader.SaveCache(); err != nil {
    71  					logger.Println(err)
    72  				}
    73  				configChannel <- config
    74  				previousChecksum = newChecksum
    75  			}
    76  		}
    77  		reader.Close()
    78  	}
    79  	close(configChannel)
    80  }