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