gitee.com/sasukebo/go-micro/v4@v4.7.1/config/default.go (about)

     1  package config
     2  
     3  import (
     4  	"bytes"
     5  	"sync"
     6  	"time"
     7  
     8  	"gitee.com/sasukebo/go-micro/v4/config/loader"
     9  	"gitee.com/sasukebo/go-micro/v4/config/loader/memory"
    10  	"gitee.com/sasukebo/go-micro/v4/config/reader"
    11  	"gitee.com/sasukebo/go-micro/v4/config/reader/json"
    12  	"gitee.com/sasukebo/go-micro/v4/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, 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  
    44  	return &c, nil
    45  }
    46  
    47  func (c *config) Init(opts ...Option) error {
    48  	c.opts = Options{
    49  		Reader: json.NewReader(),
    50  	}
    51  	c.exit = make(chan bool)
    52  	for _, o := range opts {
    53  		o(&c.opts)
    54  	}
    55  
    56  	// default loader uses the configured reader
    57  	if c.opts.Loader == nil {
    58  		loaderOpts := []loader.Option{memory.WithReader(c.opts.Reader)}
    59  		if c.opts.WithWatcherDisabled {
    60  			loaderOpts = append(loaderOpts, memory.WithWatcherDisabled())
    61  		}
    62  
    63  		c.opts.Loader = memory.NewLoader(loaderOpts...)
    64  	}
    65  
    66  	err := c.opts.Loader.Load(c.opts.Source...)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	c.snap, err = c.opts.Loader.Snapshot()
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	return nil
    82  }
    83  
    84  func (c *config) Options() Options {
    85  	return c.opts
    86  }
    87  
    88  func (c *config) run() {
    89  	watch := func(w loader.Watcher) error {
    90  		for {
    91  			// get changeset
    92  			snap, err := w.Next()
    93  			if err != nil {
    94  				return err
    95  			}
    96  
    97  			c.Lock()
    98  
    99  			if c.snap.Version >= snap.Version {
   100  				c.Unlock()
   101  				continue
   102  			}
   103  
   104  			// save
   105  			c.snap = snap
   106  
   107  			// set values
   108  			c.vals, _ = c.opts.Reader.Values(snap.ChangeSet)
   109  
   110  			c.Unlock()
   111  		}
   112  	}
   113  
   114  	for {
   115  		w, err := c.opts.Loader.Watch()
   116  		if err != nil {
   117  			time.Sleep(time.Second)
   118  			continue
   119  		}
   120  
   121  		done := make(chan bool)
   122  
   123  		// the stop watch func
   124  		go func() {
   125  			select {
   126  			case <-done:
   127  			case <-c.exit:
   128  			}
   129  			w.Stop()
   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 {
   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()
   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  	if err := c.opts.Loader.Load(sources...); err != nil {
   244  		return err
   245  	}
   246  
   247  	snap, err := c.opts.Loader.Snapshot()
   248  	if err != nil {
   249  		return err
   250  	}
   251  
   252  	c.Lock()
   253  	defer c.Unlock()
   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 := c.Get(path...)
   267  
   268  	w, err := c.opts.Loader.Watch(path...)
   269  	if err != nil {
   270  		return nil, err
   271  	}
   272  
   273  	return &watcher{
   274  		lw:    w,
   275  		rd:    c.opts.Reader,
   276  		path:  path,
   277  		value: value,
   278  	}, nil
   279  }
   280  
   281  func (c *config) String() string {
   282  	return "config"
   283  }
   284  
   285  func (w *watcher) Next() (reader.Value, error) {
   286  	for {
   287  		s, err := w.lw.Next()
   288  		if err != nil {
   289  			return nil, err
   290  		}
   291  
   292  		// only process changes
   293  		if bytes.Equal(w.value.Bytes(), s.ChangeSet.Data) {
   294  			continue
   295  		}
   296  
   297  		v, err := w.rd.Values(s.ChangeSet)
   298  		if err != nil {
   299  			return nil, err
   300  		}
   301  
   302  		w.value = v.Get()
   303  		return w.value, nil
   304  	}
   305  }
   306  
   307  func (w *watcher) Stop() error {
   308  	return w.lw.Stop()
   309  }