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 }