package polaris import ( "path/filepath" "strings" "github.com/polarismesh/polaris-go" "github.com/polarismesh/polaris-go/pkg/model" "github.com/go-kratos/kratos/v2/config" "github.com/go-kratos/kratos/v2/log" ) // ConfigOption is polaris config option. type ConfigOption func(o *configOptions) type configOptions struct { namespace string files []File configFile []polaris.ConfigFile } // WithConfigFile with polaris config file func WithConfigFile(file ...File) ConfigOption { return func(o *configOptions) { o.files = file } } type File struct { Name string Group string } type source struct { client polaris.ConfigAPI options *configOptions } // Load return the config values func (s *source) Load() ([]*config.KeyValue, error) { kv := make([]*config.KeyValue, 0) for _, file := range s.options.files { configFile, err := s.client.GetConfigFile(s.options.namespace, file.Group, file.Name) if err != nil { return nil, err } s.options.configFile = append(s.options.configFile, configFile) kv = append(kv, &config.KeyValue{ Key: file.Name, Value: []byte(configFile.GetContent()), Format: strings.TrimPrefix(filepath.Ext(file.Name), "."), }) } return kv, nil } // Watch return the watcher func (s *source) Watch() (config.Watcher, error) { return newConfigWatcher(s.options.configFile), nil } type ConfigWatcher struct { event chan model.ConfigFileChangeEvent cfg []*config.KeyValue } func receive(event chan model.ConfigFileChangeEvent) func(m model.ConfigFileChangeEvent) { return func(m model.ConfigFileChangeEvent) { defer func() { if err := recover(); err != nil { log.Error(err) } }() event <- m } } func newConfigWatcher(configFile []polaris.ConfigFile) *ConfigWatcher { w := &ConfigWatcher{ event: make(chan model.ConfigFileChangeEvent, len(configFile)), } for _, file := range configFile { w.cfg = append(w.cfg, &config.KeyValue{ Key: file.GetFileName(), Value: []byte(file.GetContent()), Format: strings.TrimPrefix(filepath.Ext(file.GetFileName()), "."), }) } for _, file := range configFile { file.AddChangeListener(receive(w.event)) } return w } func (w *ConfigWatcher) Next() ([]*config.KeyValue, error) { if event, ok := <-w.event; ok { m := make(map[string]*config.KeyValue) for _, file := range w.cfg { m[file.Key] = file } m[event.ConfigFileMetadata.GetFileName()] = &config.KeyValue{ Key: event.ConfigFileMetadata.GetFileName(), Value: []byte(event.NewValue), Format: strings.TrimPrefix(filepath.Ext(event.ConfigFileMetadata.GetFileName()), "."), } w.cfg = make([]*config.KeyValue, 0, len(m)) for _, kv := range m { w.cfg = append(w.cfg, kv) } return w.cfg, nil } return w.cfg, nil } func (w *ConfigWatcher) Stop() error { close(w.event) return nil }