go-micro.dev/v5@v5.12.0/config/default.go (about)

     1  package config
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"go-micro.dev/v5/config/loader"
     7  	"go-micro.dev/v5/config/loader/memory"
     8  	"go-micro.dev/v5/config/reader"
     9  	"go-micro.dev/v5/config/reader/json"
    10  	"go-micro.dev/v5/config/source"
    11  	"sync"
    12  	"time"
    13  )
    14  
    15  type config struct {
    16  	// the current values
    17  	vals reader.Values
    18  	exit chan bool
    19  	// the current snapshot
    20  	snap *loader.Snapshot
    21  	opts Options
    22  
    23  	sync.RWMutex
    24  }
    25  
    26  type watcher struct {
    27  	lw    loader.Watcher
    28  	rd    reader.Reader
    29  	value reader.Value
    30  	path  []string
    31  }
    32  
    33  func newConfig(opts ...Option) (Config, error) {
    34  	var c config
    35  
    36  	err := c.Init(opts...)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	if !c.opts.WithWatcherDisabled {
    41  		go c.run()
    42  	}
    43  	return &c, nil
    44  }
    45  
    46  func (c *config) Init(opts ...Option) error {
    47  	c.opts = Options{
    48  		Reader: json.NewReader(),
    49  	}
    50  	c.exit = make(chan bool)
    51  	for _, o := range opts {
    52  		o(&c.opts)
    53  	}
    54  
    55  	// default loader uses the configured reader
    56  	if c.opts.Loader == nil {
    57  		loaderOpts := []loader.Option{memory.WithReader(c.opts.Reader)}
    58  		if c.opts.WithWatcherDisabled {
    59  			loaderOpts = append(loaderOpts, memory.WithWatcherDisabled())
    60  		}
    61  
    62  		c.opts.Loader = memory.NewLoader(loaderOpts...)
    63  	}
    64  
    65  	err := c.opts.Loader.Load(c.opts.Source...)
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	c.snap, err = c.opts.Loader.Snapshot()
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet)
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  func (c *config) Options() Options {
    84  	return c.opts
    85  }
    86  
    87  func (c *config) run() {
    88  	watch := func(w loader.Watcher) error {
    89  		for {
    90  			// get changeset
    91  			snap, err := w.Next()
    92  			if err != nil {
    93  				return err
    94  			}
    95  
    96  			c.Lock()
    97  
    98  			if c.snap.Version >= snap.Version {
    99  				c.Unlock()
   100  				continue
   101  			}
   102  
   103  			// save
   104  			c.snap = snap
   105  
   106  			// set values
   107  			c.vals, _ = c.opts.Reader.Values(snap.ChangeSet)
   108  
   109  			c.Unlock()
   110  		}
   111  	}
   112  
   113  	for {
   114  		w, err := c.opts.Loader.Watch()
   115  		if err != nil {
   116  			time.Sleep(time.Second)
   117  			continue
   118  		}
   119  
   120  		done := make(chan bool)
   121  
   122  		// the stop watch func
   123  		go func() {
   124  			select {
   125  			case <-done:
   126  			case <-c.exit:
   127  			}
   128  			err := w.Stop()
   129  			fmt.Println(err)
   130  		}()
   131  
   132  		// block watch
   133  		if err := watch(w); err != nil {
   134  			// do something better
   135  			time.Sleep(time.Second)
   136  		}
   137  
   138  		// close done chan
   139  		close(done)
   140  
   141  		// if the config is closed exit
   142  		select {
   143  		case <-c.exit:
   144  			return
   145  		default:
   146  		}
   147  	}
   148  }
   149  
   150  func (c *config) Map() map[string]interface{} {
   151  	c.RLock()
   152  	defer c.RUnlock()
   153  	return c.vals.Map()
   154  }
   155  
   156  func (c *config) Scan(v interface{}) error {
   157  	c.RLock()
   158  	defer c.RUnlock()
   159  	return c.vals.Scan(v)
   160  }
   161  
   162  // sync loads all the sources, calls the parser and updates the config.
   163  func (c *config) Sync() error {
   164  	if err := c.opts.Loader.Sync(); err != nil {
   165  		return err
   166  	}
   167  
   168  	snap, err := c.opts.Loader.Snapshot()
   169  	if err != nil {
   170  		return err
   171  	}
   172  
   173  	c.Lock()
   174  	defer c.Unlock()
   175  
   176  	c.snap = snap
   177  	vals, err := c.opts.Reader.Values(snap.ChangeSet)
   178  	if err != nil {
   179  		return err
   180  	}
   181  	c.vals = vals
   182  
   183  	return nil
   184  }
   185  
   186  func (c *config) Close() error {
   187  	select {
   188  	case <-c.exit:
   189  		return nil
   190  	default:
   191  		close(c.exit)
   192  	}
   193  	return nil
   194  }
   195  
   196  func (c *config) Get(path ...string) (reader.Value, error) {
   197  	c.RLock()
   198  	defer c.RUnlock()
   199  
   200  	// did sync actually work?
   201  	if c.vals != nil {
   202  		return c.vals.Get(path...)
   203  	}
   204  
   205  	// no value
   206  	return newValue(), nil
   207  }
   208  
   209  func (c *config) Set(val interface{}, path ...string) {
   210  	c.Lock()
   211  	defer c.Unlock()
   212  
   213  	if c.vals != nil {
   214  		c.vals.Set(val, path...)
   215  	}
   216  
   217  	return
   218  }
   219  
   220  func (c *config) Del(path ...string) {
   221  	c.Lock()
   222  	defer c.Unlock()
   223  
   224  	if c.vals != nil {
   225  		c.vals.Del(path...)
   226  	}
   227  
   228  	return
   229  }
   230  
   231  func (c *config) Bytes() []byte {
   232  	c.RLock()
   233  	defer c.RUnlock()
   234  
   235  	if c.vals == nil {
   236  		return []byte{}
   237  	}
   238  
   239  	return c.vals.Bytes()
   240  }
   241  
   242  func (c *config) Load(sources ...source.Source) error {
   243  	c.Lock()
   244  	defer c.Unlock()
   245  
   246  	if err := c.opts.Loader.Load(sources...); err != nil {
   247  		return err
   248  	}
   249  
   250  	snap, err := c.opts.Loader.Snapshot()
   251  	if err != nil {
   252  		return err
   253  	}
   254  
   255  	c.snap = snap
   256  	vals, err := c.opts.Reader.Values(snap.ChangeSet)
   257  	if err != nil {
   258  		return err
   259  	}
   260  	c.vals = vals
   261  
   262  	return nil
   263  }
   264  
   265  func (c *config) Watch(path ...string) (Watcher, error) {
   266  	value, err := c.Get(path...)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  
   271  	w, err := c.opts.Loader.Watch(path...)
   272  	if err != nil {
   273  		return nil, err
   274  	}
   275  
   276  	return &watcher{
   277  		lw:    w,
   278  		rd:    c.opts.Reader,
   279  		path:  path,
   280  		value: value,
   281  	}, nil
   282  }
   283  
   284  func (c *config) String() string {
   285  	return "config"
   286  }
   287  
   288  func (w *watcher) Next() (reader.Value, error) {
   289  	for {
   290  		s, err := w.lw.Next()
   291  		if err != nil {
   292  			return nil, err
   293  		}
   294  
   295  		// only process changes
   296  		if bytes.Equal(w.value.Bytes(), s.ChangeSet.Data) {
   297  			continue
   298  		}
   299  
   300  		v, err := w.rd.Values(s.ChangeSet)
   301  		if err != nil {
   302  			return nil, err
   303  		}
   304  
   305  		return v.Get()
   306  	}
   307  }
   308  
   309  func (w *watcher) Stop() error {
   310  	return w.lw.Stop()
   311  }