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 }