gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/config/default.go (about)

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