trpc.group/trpc-go/trpc-go@v1.0.3/config/config.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  // Package config provides common config interface.
    15  package config
    16  
    17  import (
    18  	"context"
    19  	"encoding/json"
    20  	"errors"
    21  	"fmt"
    22  	"strconv"
    23  	"sync"
    24  
    25  	"github.com/BurntSushi/toml"
    26  	yaml "gopkg.in/yaml.v3"
    27  )
    28  
    29  // ErrConfigNotSupport is not supported config error
    30  var ErrConfigNotSupport = errors.New("trpc/config: not support")
    31  
    32  // GetString returns string value get from
    33  // kv storage by key.
    34  func GetString(key string) (string, error) {
    35  	val, err := globalKV.Get(context.Background(), key)
    36  	if err != nil {
    37  		return "", err
    38  	}
    39  	return val.Value(), nil
    40  }
    41  
    42  // GetStringWithDefault returns string value get by key.
    43  // If anything wrong, returns default value specified by input param def.
    44  func GetStringWithDefault(key, def string) string {
    45  	val, err := globalKV.Get(context.Background(), key)
    46  	if err != nil {
    47  		return def
    48  	}
    49  	return val.Value()
    50  }
    51  
    52  // GetInt returns int value get by key.
    53  func GetInt(key string) (int, error) {
    54  	val, err := globalKV.Get(context.Background(), key)
    55  	if err != nil {
    56  		return 0, err
    57  	}
    58  	return strconv.Atoi(val.Value())
    59  }
    60  
    61  // GetIntWithDefault returns int value get by key.
    62  // If anything wrong, returns default value specified by input param def.
    63  func GetIntWithDefault(key string, def int) int {
    64  	val, err := globalKV.Get(context.Background(), key)
    65  	if err != nil {
    66  		return def
    67  	}
    68  	i, err := strconv.Atoi(val.Value())
    69  	if err != nil {
    70  		return def
    71  	}
    72  	return i
    73  }
    74  
    75  // GetWithUnmarshal gets the specific encoding data
    76  // by key. the encoding type is defined by unmarshalName parameter.
    77  func GetWithUnmarshal(key string, val interface{}, unmarshalName string) error {
    78  	v, err := globalKV.Get(context.Background(), key)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	return GetUnmarshaler(unmarshalName).Unmarshal([]byte(v.Value()), val)
    83  }
    84  
    85  // GetWithUnmarshalProvider gets the specific encoding data by key
    86  // the encoding type is defined by unmarshalName parameter
    87  // the provider name is defined by provider parameter.
    88  func GetWithUnmarshalProvider(key string, val interface{}, unmarshalName string, provider string) error {
    89  	p := Get(provider)
    90  	if p == nil {
    91  		return fmt.Errorf("trpc/config: failed to get %s", provider)
    92  	}
    93  	v, err := p.Get(context.Background(), key)
    94  	if err != nil {
    95  		return err
    96  	}
    97  	return GetUnmarshaler(unmarshalName).Unmarshal([]byte(v.Value()), val)
    98  }
    99  
   100  // GetJSON gets json data by key. The value will unmarshal into val parameter.
   101  func GetJSON(key string, val interface{}) error {
   102  	return GetWithUnmarshal(key, val, "json")
   103  }
   104  
   105  // GetJSONWithProvider gets json data by key. The value will unmarshal into val parameter
   106  // the provider name is defined by provider parameter.
   107  func GetJSONWithProvider(key string, val interface{}, provider string) error {
   108  	return GetWithUnmarshalProvider(key, val, "json", provider)
   109  }
   110  
   111  // GetYAML gets yaml data by key. The value will unmarshal into val parameter.
   112  func GetYAML(key string, val interface{}) error {
   113  	return GetWithUnmarshal(key, val, "yaml")
   114  }
   115  
   116  // GetYAMLWithProvider gets yaml data by key. The value will unmarshal into val parameter
   117  // the provider name is defined by provider parameter.
   118  func GetYAMLWithProvider(key string, val interface{}, provider string) error {
   119  	return GetWithUnmarshalProvider(key, val, "yaml", provider)
   120  }
   121  
   122  // GetTOML gets toml data by key. The value will unmarshal into val parameter.
   123  func GetTOML(key string, val interface{}) error {
   124  	return GetWithUnmarshal(key, val, "toml")
   125  }
   126  
   127  // GetTOMLWithProvider gets toml data by key. The value will unmarshal into val parameter
   128  // the provider name is defined by provider parameter.
   129  func GetTOMLWithProvider(key string, val interface{}, provider string) error {
   130  	return GetWithUnmarshalProvider(key, val, "toml", provider)
   131  }
   132  
   133  // Unmarshaler defines a unmarshal interface, this will
   134  // be used to parse config data.
   135  type Unmarshaler interface {
   136  	// Unmarshal deserializes the data bytes into value parameter.
   137  	Unmarshal(data []byte, value interface{}) error
   138  }
   139  
   140  var (
   141  	unmarshalers = make(map[string]Unmarshaler)
   142  )
   143  
   144  // YamlUnmarshaler is yaml unmarshaler.
   145  type YamlUnmarshaler struct{}
   146  
   147  // Unmarshal deserializes the data bytes into parameter val in yaml protocol.
   148  func (yu *YamlUnmarshaler) Unmarshal(data []byte, val interface{}) error {
   149  	return yaml.Unmarshal(data, val)
   150  }
   151  
   152  // JSONUnmarshaler is json unmarshaler.
   153  type JSONUnmarshaler struct{}
   154  
   155  // Unmarshal deserializes the data bytes into parameter val in json protocol.
   156  func (ju *JSONUnmarshaler) Unmarshal(data []byte, val interface{}) error {
   157  	return json.Unmarshal(data, val)
   158  }
   159  
   160  // TomlUnmarshaler is toml unmarshaler.
   161  type TomlUnmarshaler struct{}
   162  
   163  // Unmarshal deserializes the data bytes into parameter val in toml protocol.
   164  func (tu *TomlUnmarshaler) Unmarshal(data []byte, val interface{}) error {
   165  	return toml.Unmarshal(data, val)
   166  }
   167  
   168  func init() {
   169  	RegisterUnmarshaler("yaml", &YamlUnmarshaler{})
   170  	RegisterUnmarshaler("json", &JSONUnmarshaler{})
   171  	RegisterUnmarshaler("toml", &TomlUnmarshaler{})
   172  }
   173  
   174  // RegisterUnmarshaler registers an unmarshaler by name.
   175  func RegisterUnmarshaler(name string, us Unmarshaler) {
   176  	unmarshalers[name] = us
   177  }
   178  
   179  // GetUnmarshaler returns an unmarshaler by name.
   180  func GetUnmarshaler(name string) Unmarshaler {
   181  	return unmarshalers[name]
   182  }
   183  
   184  var (
   185  	configMap = make(map[string]KVConfig)
   186  )
   187  
   188  // KVConfig defines a kv config interface.
   189  type KVConfig interface {
   190  	KV
   191  	Watcher
   192  	Name() string
   193  }
   194  
   195  // Register registers a kv config by its name.
   196  func Register(c KVConfig) {
   197  	lock.Lock()
   198  	configMap[c.Name()] = c
   199  	lock.Unlock()
   200  }
   201  
   202  // Get returns a kv config by name.
   203  func Get(name string) KVConfig {
   204  	lock.RLock()
   205  	c := configMap[name]
   206  	lock.RUnlock()
   207  	return c
   208  }
   209  
   210  // GlobalKV returns an instance of kv config center.
   211  func GlobalKV() KV {
   212  	return globalKV
   213  }
   214  
   215  // SetGlobalKV sets the instance of kv config center.
   216  func SetGlobalKV(kv KV) {
   217  	globalKV = kv
   218  }
   219  
   220  // EventType defines the event type of config change.
   221  type EventType uint8
   222  
   223  const (
   224  	// EventTypeNull represents null event.
   225  	EventTypeNull EventType = 0
   226  
   227  	// EventTypePut represents set or update config event.
   228  	EventTypePut EventType = 1
   229  
   230  	// EventTypeDel represents delete config event.
   231  	EventTypeDel EventType = 2
   232  )
   233  
   234  // Response defines config center's response interface.
   235  type Response interface {
   236  	// Value returns config value as string.
   237  	Value() string
   238  
   239  	// MetaData returns extra metadata. With option,
   240  	// we can implement some extra features for different config center,
   241  	// such as namespace, group, lease, etc.
   242  	MetaData() map[string]string
   243  
   244  	// Event returns the type of watch event.
   245  	Event() EventType
   246  }
   247  
   248  // KV defines a kv storage for config center.
   249  type KV interface {
   250  	// Put puts or updates config value by key.
   251  	Put(ctx context.Context, key, val string, opts ...Option) error
   252  
   253  	// Get returns config value by key.
   254  	Get(ctx context.Context, key string, opts ...Option) (Response, error)
   255  
   256  	// Del deletes config value by key.
   257  	Del(ctx context.Context, key string, opts ...Option) error
   258  }
   259  
   260  // Watcher defines the interface of config center watch event.
   261  type Watcher interface {
   262  	// Watch watches the config key change event.
   263  	Watch(ctx context.Context, key string, opts ...Option) (<-chan Response, error)
   264  }
   265  
   266  var globalKV KV = &noopKV{}
   267  
   268  // noopKV is an empty implementation of KV interface.
   269  type noopKV struct{}
   270  
   271  // Put does nothing but returns nil.
   272  func (kv *noopKV) Put(ctx context.Context, key, val string, opts ...Option) error {
   273  	return nil
   274  }
   275  
   276  // Get returns not supported error.
   277  func (kv *noopKV) Get(ctx context.Context, key string, opts ...Option) (Response, error) {
   278  	return nil, ErrConfigNotSupport
   279  }
   280  
   281  // Del does nothing but returns nil.
   282  func (kv *noopKV) Del(ctx context.Context, key string, opts ...Option) error {
   283  	return nil
   284  }
   285  
   286  // Config defines the common config interface. We can
   287  // implement different config center by this interface.
   288  type Config interface {
   289  	// Load loads config.
   290  	Load() error
   291  
   292  	// Reload reloads config.
   293  	Reload()
   294  
   295  	// Get returns config by key.
   296  	Get(string, interface{}) interface{}
   297  
   298  	// Unmarshal deserializes the config into input param.
   299  	Unmarshal(interface{}) error
   300  
   301  	// IsSet returns if the config specified by key exists.
   302  	IsSet(string) bool
   303  
   304  	// GetInt returns int value by key, the second parameter
   305  	// is default value when key is absent or type conversion fails.
   306  	GetInt(string, int) int
   307  
   308  	// GetInt32 returns int32 value by key, the second parameter
   309  	// is default value when key is absent or type conversion fails.
   310  	GetInt32(string, int32) int32
   311  
   312  	// GetInt64 returns int64 value by key, the second parameter
   313  	// is default value when key is absent or type conversion fails.
   314  	GetInt64(string, int64) int64
   315  
   316  	// GetUint returns uint value by key, the second parameter
   317  	// is default value when key is absent or type conversion fails.
   318  	GetUint(string, uint) uint
   319  
   320  	// GetUint32 returns uint32 value by key, the second parameter
   321  	// is default value when key is absent or type conversion fails.
   322  	GetUint32(string, uint32) uint32
   323  
   324  	// GetUint64 returns uint64 value by key, the second parameter
   325  	// is default value when key is absent or type conversion fails.
   326  	GetUint64(string, uint64) uint64
   327  
   328  	// GetFloat32 returns float32 value by key, the second parameter
   329  	// is default value when key is absent or type conversion fails.
   330  	GetFloat32(string, float32) float32
   331  
   332  	// GetFloat64 returns float64 value by key, the second parameter
   333  	// is default value when key is absent or type conversion fails.
   334  	GetFloat64(string, float64) float64
   335  
   336  	// GetString returns string value by key, the second parameter
   337  	// is default value when key is absent or type conversion fails.
   338  	GetString(string, string) string
   339  
   340  	// GetBool returns bool value by key, the second parameter
   341  	// is default value when key is absent or type conversion fails.
   342  	GetBool(string, bool) bool
   343  
   344  	// Bytes returns config data as bytes.
   345  	Bytes() []byte
   346  }
   347  
   348  // ProviderCallback is callback function for provider to handle
   349  // config change.
   350  type ProviderCallback func(string, []byte)
   351  
   352  // DataProvider defines common data provider interface.
   353  // we can implement this interface to define different
   354  // data provider( such as file, TConf, ETCD, configmap)
   355  // and parse config data to standard format( such as json,
   356  // toml, yaml, etc.) by codec.
   357  type DataProvider interface {
   358  	// Name returns the data provider's name.
   359  	Name() string
   360  
   361  	// Read reads the specific path file, returns
   362  	// it content as bytes.
   363  	Read(string) ([]byte, error)
   364  
   365  	// Watch watches config changing. The change will
   366  	// be handled by callback function.
   367  	Watch(ProviderCallback)
   368  }
   369  
   370  // Codec defines codec interface.
   371  type Codec interface {
   372  
   373  	// Name returns codec's name.
   374  	Name() string
   375  
   376  	// Unmarshal deserializes the config data bytes into
   377  	// the second input parameter.
   378  	Unmarshal([]byte, interface{}) error
   379  }
   380  
   381  var providerMap = make(map[string]DataProvider)
   382  
   383  // RegisterProvider registers a data provider by its name.
   384  func RegisterProvider(p DataProvider) {
   385  	providerMap[p.Name()] = p
   386  }
   387  
   388  // GetProvider returns the provider by name.
   389  func GetProvider(name string) DataProvider {
   390  	return providerMap[name]
   391  }
   392  
   393  var (
   394  	codecMap = make(map[string]Codec)
   395  	lock     = sync.RWMutex{}
   396  )
   397  
   398  // RegisterCodec registers codec by its name.
   399  func RegisterCodec(c Codec) {
   400  	lock.Lock()
   401  	codecMap[c.Name()] = c
   402  	lock.Unlock()
   403  }
   404  
   405  // GetCodec returns the codec by name.
   406  func GetCodec(name string) Codec {
   407  	lock.RLock()
   408  	c := codecMap[name]
   409  	lock.RUnlock()
   410  	return c
   411  }
   412  
   413  // Load returns the config specified by input parameter.
   414  func Load(path string, opts ...LoadOption) (Config, error) {
   415  	return DefaultConfigLoader.Load(path, opts...)
   416  }
   417  
   418  // Reload reloads config data.
   419  func Reload(path string, opts ...LoadOption) error {
   420  	return DefaultConfigLoader.Reload(path, opts...)
   421  }