github.com/rudderlabs/rudder-go-kit@v0.30.0/config/hotreloadable.go (about) 1 package config 2 3 import ( 4 "strings" 5 "sync" 6 "time" 7 ) 8 9 // RegisterIntConfigVariable registers int config variable 10 // 11 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 12 // e.g. asking for the same keys but in a different order can result in a different value to be returned 13 // 14 // Deprecated: use GetIntVar or GetReloadableIntVar instead 15 func RegisterIntConfigVariable(defaultValue int, ptr *int, isHotReloadable bool, valueScale int, orderedKeys ...string) { 16 Default.RegisterIntConfigVariable(defaultValue, ptr, isHotReloadable, valueScale, orderedKeys...) 17 } 18 19 // GetIntVar registers a not hot-reloadable int config variable 20 // 21 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 22 // e.g. asking for the same keys but in a different order can result in a different value to be returned 23 func GetIntVar(defaultValue, valueScale int, orderedKeys ...string) int { 24 return Default.GetIntVar(defaultValue, valueScale, orderedKeys...) 25 } 26 27 // GetReloadableIntVar registers a hot-reloadable int config variable 28 // 29 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 30 // e.g. asking for the same keys but in a different order can result in a different value to be returned 31 func GetReloadableIntVar(defaultValue, valueScale int, orderedKeys ...string) *Reloadable[int] { 32 return Default.GetReloadableIntVar(defaultValue, valueScale, orderedKeys...) 33 } 34 35 // RegisterIntConfigVariable registers int config variable 36 // 37 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 38 // e.g. asking for the same keys but in a different order can result in a different value to be returned 39 // 40 // Deprecated: use GetIntVar or GetReloadableIntVar instead 41 func (c *Config) RegisterIntConfigVariable( 42 defaultValue int, ptr *int, isHotReloadable bool, valueScale int, orderedKeys ...string, 43 ) { 44 c.registerIntVar(defaultValue, ptr, isHotReloadable, valueScale, func(v int) { 45 *ptr = v 46 }, orderedKeys...) 47 } 48 49 // GetIntVar registers a not hot-reloadable int config variable 50 // 51 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 52 // e.g. asking for the same keys but in a different order can result in a different value to be returned 53 func (c *Config) GetIntVar(defaultValue, valueScale int, orderedKeys ...string) int { 54 var ret int 55 c.registerIntVar(defaultValue, nil, false, valueScale, func(v int) { 56 ret = v 57 }, orderedKeys...) 58 return ret 59 } 60 61 // GetReloadableIntVar registers a hot-reloadable int config variable 62 // 63 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 64 // e.g. asking for the same keys but in a different order can result in a different value to be returned 65 func (c *Config) GetReloadableIntVar(defaultValue, valueScale int, orderedKeys ...string) *Reloadable[int] { 66 ptr, exists := getOrCreatePointer( 67 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, defaultValue*valueScale, orderedKeys..., 68 ) 69 if !exists { 70 c.registerIntVar(defaultValue, ptr, true, valueScale, func(v int) { 71 ptr.store(v) 72 }, orderedKeys...) 73 } 74 return ptr 75 } 76 77 func (c *Config) registerIntVar( 78 defaultValue int, ptr any, isHotReloadable bool, valueScale int, store func(int), orderedKeys ...string, 79 ) { 80 configVar := configValue{ 81 value: ptr, 82 multiplier: valueScale, 83 defaultValue: defaultValue, 84 keys: orderedKeys, 85 } 86 87 if isHotReloadable { 88 c.hotReloadableConfigLock.Lock() 89 c.appendVarToConfigMaps(orderedKeys, &configVar) 90 c.hotReloadableConfigLock.Unlock() 91 } 92 93 for _, key := range orderedKeys { 94 if c.IsSet(key) { 95 store(c.GetInt(key, defaultValue) * valueScale) 96 return 97 } 98 } 99 store(defaultValue * valueScale) 100 } 101 102 // RegisterBoolConfigVariable registers bool config variable 103 // 104 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 105 // e.g. asking for the same keys but in a different order can result in a different value to be returned 106 // 107 // Deprecated: use GetBoolVar or GetReloadableBoolVar instead 108 func RegisterBoolConfigVariable(defaultValue bool, ptr *bool, isHotReloadable bool, orderedKeys ...string) { 109 Default.RegisterBoolConfigVariable(defaultValue, ptr, isHotReloadable, orderedKeys...) 110 } 111 112 // GetBoolVar registers a not hot-reloadable bool config variable 113 // 114 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 115 // e.g. asking for the same keys but in a different order can result in a different value to be returned 116 func GetBoolVar(defaultValue bool, orderedKeys ...string) bool { 117 return Default.GetBoolVar(defaultValue, orderedKeys...) 118 } 119 120 // GetReloadableBoolVar registers a hot-reloadable bool config variable 121 // 122 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 123 // e.g. asking for the same keys but in a different order can result in a different value to be returned 124 func GetReloadableBoolVar(defaultValue bool, orderedKeys ...string) *Reloadable[bool] { 125 return Default.GetReloadableBoolVar(defaultValue, orderedKeys...) 126 } 127 128 // RegisterBoolConfigVariable registers bool config variable 129 // 130 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 131 // e.g. asking for the same keys but in a different order can result in a different value to be returned 132 // 133 // Deprecated: use GetBoolVar or GetReloadableBoolVar instead 134 func (c *Config) RegisterBoolConfigVariable(defaultValue bool, ptr *bool, isHotReloadable bool, orderedKeys ...string) { 135 c.registerBoolVar(defaultValue, ptr, isHotReloadable, func(v bool) { 136 *ptr = v 137 }, orderedKeys...) 138 } 139 140 // GetBoolVar registers a not hot-reloadable bool config variable 141 // 142 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 143 // e.g. asking for the same keys but in a different order can result in a different value to be returned 144 func (c *Config) GetBoolVar(defaultValue bool, orderedKeys ...string) bool { 145 var ret bool 146 c.registerBoolVar(defaultValue, nil, false, func(v bool) { 147 ret = v 148 }, orderedKeys...) 149 return ret 150 } 151 152 // GetReloadableBoolVar registers a hot-reloadable bool config variable 153 // 154 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 155 // e.g. asking for the same keys but in a different order can result in a different value to be returned 156 func (c *Config) GetReloadableBoolVar(defaultValue bool, orderedKeys ...string) *Reloadable[bool] { 157 ptr, exists := getOrCreatePointer( 158 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, defaultValue, orderedKeys..., 159 ) 160 if !exists { 161 c.registerBoolVar(defaultValue, ptr, true, func(v bool) { 162 ptr.store(v) 163 }, orderedKeys...) 164 } 165 return ptr 166 } 167 168 func (c *Config) registerBoolVar(defaultValue bool, ptr any, isHotReloadable bool, store func(bool), orderedKeys ...string) { 169 configVar := configValue{ 170 value: ptr, 171 defaultValue: defaultValue, 172 keys: orderedKeys, 173 } 174 175 if isHotReloadable { 176 c.hotReloadableConfigLock.Lock() 177 c.appendVarToConfigMaps(orderedKeys, &configVar) 178 c.hotReloadableConfigLock.Unlock() 179 } 180 181 for _, key := range orderedKeys { 182 c.bindEnv(key) 183 if c.IsSet(key) { 184 store(c.GetBool(key, defaultValue)) 185 return 186 } 187 } 188 store(defaultValue) 189 } 190 191 // RegisterFloat64ConfigVariable registers float64 config variable 192 // 193 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 194 // e.g. asking for the same keys but in a different order can result in a different value to be returned 195 // 196 // Deprecated: use GetFloat64Var or GetReloadableFloat64Var instead 197 func RegisterFloat64ConfigVariable(defaultValue float64, ptr *float64, isHotReloadable bool, orderedKeys ...string) { 198 Default.RegisterFloat64ConfigVariable(defaultValue, ptr, isHotReloadable, orderedKeys...) 199 } 200 201 // GetFloat64Var registers a not hot-reloadable float64 config variable 202 // 203 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 204 // e.g. asking for the same keys but in a different order can result in a different value to be returned 205 func GetFloat64Var(defaultValue float64, orderedKeys ...string) float64 { 206 return Default.GetFloat64Var(defaultValue, orderedKeys...) 207 } 208 209 // GetReloadableFloat64Var registers a hot-reloadable float64 config variable 210 // 211 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 212 // e.g. asking for the same keys but in a different order can result in a different value to be returned 213 func GetReloadableFloat64Var(defaultValue float64, orderedKeys ...string) *Reloadable[float64] { 214 return Default.GetReloadableFloat64Var(defaultValue, orderedKeys...) 215 } 216 217 // RegisterFloat64ConfigVariable registers float64 config variable 218 // 219 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 220 // e.g. asking for the same keys but in a different order can result in a different value to be returned 221 // 222 // Deprecated: use GetFloat64Var or GetReloadableFloat64Var instead 223 func (c *Config) RegisterFloat64ConfigVariable( 224 defaultValue float64, ptr *float64, isHotReloadable bool, orderedKeys ...string, 225 ) { 226 c.registerFloat64Var(defaultValue, ptr, isHotReloadable, func(v float64) { 227 *ptr = v 228 }, orderedKeys...) 229 } 230 231 // GetFloat64Var registers a not hot-reloadable float64 config variable 232 // 233 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 234 // e.g. asking for the same keys but in a different order can result in a different value to be returned 235 func (c *Config) GetFloat64Var(defaultValue float64, orderedKeys ...string) float64 { 236 var ret float64 237 c.registerFloat64Var(defaultValue, nil, false, func(v float64) { 238 ret = v 239 }, orderedKeys...) 240 return ret 241 } 242 243 // GetReloadableFloat64Var registers a hot-reloadable float64 config variable 244 // 245 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 246 // e.g. asking for the same keys but in a different order can result in a different value to be returned 247 func (c *Config) GetReloadableFloat64Var(defaultValue float64, orderedKeys ...string) *Reloadable[float64] { 248 ptr, exists := getOrCreatePointer( 249 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, defaultValue, orderedKeys..., 250 ) 251 if !exists { 252 c.registerFloat64Var(defaultValue, ptr, true, func(v float64) { 253 ptr.store(v) 254 }, orderedKeys...) 255 } 256 return ptr 257 } 258 259 func (c *Config) registerFloat64Var( 260 defaultValue float64, ptr any, isHotReloadable bool, store func(float64), orderedKeys ...string, 261 ) { 262 configVar := configValue{ 263 value: ptr, 264 multiplier: 1.0, 265 defaultValue: defaultValue, 266 keys: orderedKeys, 267 } 268 269 if isHotReloadable { 270 c.hotReloadableConfigLock.Lock() 271 c.appendVarToConfigMaps(orderedKeys, &configVar) 272 c.hotReloadableConfigLock.Unlock() 273 } 274 275 for _, key := range orderedKeys { 276 c.bindEnv(key) 277 if c.IsSet(key) { 278 store(c.GetFloat64(key, defaultValue)) 279 return 280 } 281 } 282 store(defaultValue) 283 } 284 285 // RegisterInt64ConfigVariable registers int64 config variable 286 // 287 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 288 // e.g. asking for the same keys but in a different order can result in a different value to be returned 289 // 290 // Deprecated: use GetInt64Var or GetReloadableInt64Var instead 291 func RegisterInt64ConfigVariable(defaultValue int64, ptr *int64, isHotReloadable bool, valueScale int64, orderedKeys ...string) { 292 Default.RegisterInt64ConfigVariable(defaultValue, ptr, isHotReloadable, valueScale, orderedKeys...) 293 } 294 295 // GetInt64Var registers a not hot-reloadable int64 config variable 296 // 297 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 298 // e.g. asking for the same keys but in a different order can result in a different value to be returned 299 func GetInt64Var(defaultValue, valueScale int64, orderedKeys ...string) int64 { 300 return Default.GetInt64Var(defaultValue, valueScale, orderedKeys...) 301 } 302 303 // GetReloadableInt64Var registers a hot-reloadable int64 config variable 304 // 305 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 306 // e.g. asking for the same keys but in a different order can result in a different value to be returned 307 func GetReloadableInt64Var(defaultValue, valueScale int64, orderedKeys ...string) *Reloadable[int64] { 308 return Default.GetReloadableInt64Var(defaultValue, valueScale, orderedKeys...) 309 } 310 311 // RegisterInt64ConfigVariable registers int64 config variable 312 // 313 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 314 // e.g. asking for the same keys but in a different order can result in a different value to be returned 315 // 316 // Deprecated: use GetInt64Var or GetReloadableInt64Var instead 317 func (c *Config) RegisterInt64ConfigVariable( 318 defaultValue int64, ptr *int64, isHotReloadable bool, valueScale int64, orderedKeys ...string, 319 ) { 320 c.registerInt64Var(defaultValue, ptr, isHotReloadable, valueScale, func(v int64) { 321 *ptr = v 322 }, orderedKeys...) 323 } 324 325 // GetInt64Var registers a not hot-reloadable int64 config variable 326 // 327 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 328 // e.g. asking for the same keys but in a different order can result in a different value to be returned 329 func (c *Config) GetInt64Var(defaultValue, valueScale int64, orderedKeys ...string) int64 { 330 var ret int64 331 c.registerInt64Var(defaultValue, nil, false, valueScale, func(v int64) { 332 ret = v 333 }, orderedKeys...) 334 return ret 335 } 336 337 // GetReloadableInt64Var registers a not hot-reloadable int64 config variable 338 // 339 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 340 // e.g. asking for the same keys but in a different order can result in a different value to be returned 341 func (c *Config) GetReloadableInt64Var(defaultValue, valueScale int64, orderedKeys ...string) *Reloadable[int64] { 342 ptr, exists := getOrCreatePointer( 343 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, defaultValue*valueScale, orderedKeys..., 344 ) 345 if !exists { 346 c.registerInt64Var(defaultValue, ptr, true, valueScale, func(v int64) { 347 ptr.store(v) 348 }, orderedKeys...) 349 } 350 return ptr 351 } 352 353 func (c *Config) registerInt64Var( 354 defaultValue int64, ptr any, isHotReloadable bool, valueScale int64, store func(int64), orderedKeys ...string, 355 ) { 356 configVar := configValue{ 357 value: ptr, 358 multiplier: valueScale, 359 defaultValue: defaultValue, 360 keys: orderedKeys, 361 } 362 363 if isHotReloadable { 364 c.hotReloadableConfigLock.Lock() 365 c.appendVarToConfigMaps(orderedKeys, &configVar) 366 c.hotReloadableConfigLock.Unlock() 367 } 368 369 for _, key := range orderedKeys { 370 c.bindEnv(key) 371 if c.IsSet(key) { 372 store(c.GetInt64(key, defaultValue) * valueScale) 373 return 374 } 375 } 376 store(defaultValue * valueScale) 377 } 378 379 // RegisterDurationConfigVariable registers duration config variable 380 // 381 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 382 // e.g. asking for the same keys but in a different order can result in a different value to be returned 383 // 384 // Deprecated: use GetDurationVar or GetReloadableDurationVar instead 385 func RegisterDurationConfigVariable( 386 defaultValueInTimescaleUnits int64, ptr *time.Duration, isHotReloadable bool, timeScale time.Duration, orderedKeys ...string, 387 ) { 388 Default.RegisterDurationConfigVariable(defaultValueInTimescaleUnits, ptr, isHotReloadable, timeScale, orderedKeys...) 389 } 390 391 // GetDurationVar registers a not hot-reloadable duration config variable 392 // 393 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 394 // e.g. asking for the same keys but in a different order can result in a different value to be returned 395 func GetDurationVar( 396 defaultValueInTimescaleUnits int64, timeScale time.Duration, orderedKeys ...string, 397 ) time.Duration { 398 return Default.GetDurationVar(defaultValueInTimescaleUnits, timeScale, orderedKeys...) 399 } 400 401 // GetReloadableDurationVar registers a not hot-reloadable duration config variable 402 // 403 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 404 // e.g. asking for the same keys but in a different order can result in a different value to be returned 405 func GetReloadableDurationVar(defaultValueInTimescaleUnits int64, timeScale time.Duration, orderedKeys ...string) *Reloadable[time.Duration] { 406 return Default.GetReloadableDurationVar(defaultValueInTimescaleUnits, timeScale, orderedKeys...) 407 } 408 409 // RegisterDurationConfigVariable registers duration config variable 410 // 411 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 412 // e.g. asking for the same keys but in a different order can result in a different value to be returned 413 // 414 // Deprecated: use GetDurationVar or GetReloadableDurationVar instead 415 func (c *Config) RegisterDurationConfigVariable( 416 defaultValueInTimescaleUnits int64, ptr *time.Duration, isHotReloadable bool, timeScale time.Duration, orderedKeys ...string, 417 ) { 418 c.registerDurationVar(defaultValueInTimescaleUnits, ptr, isHotReloadable, timeScale, func(v time.Duration) { 419 *ptr = v 420 }, orderedKeys...) 421 } 422 423 // GetDurationVar registers a not hot-reloadable duration config variable 424 // 425 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 426 // e.g. asking for the same keys but in a different order can result in a different value to be returned 427 func (c *Config) GetDurationVar( 428 defaultValueInTimescaleUnits int64, timeScale time.Duration, orderedKeys ...string, 429 ) time.Duration { 430 var ret time.Duration 431 c.registerDurationVar(defaultValueInTimescaleUnits, nil, false, timeScale, func(v time.Duration) { 432 ret = v 433 }, orderedKeys...) 434 return ret 435 } 436 437 // GetReloadableDurationVar registers a hot-reloadable duration config variable 438 // 439 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 440 // e.g. asking for the same keys but in a different order can result in a different value to be returned 441 func (c *Config) GetReloadableDurationVar( 442 defaultValueInTimescaleUnits int64, timeScale time.Duration, orderedKeys ...string, 443 ) *Reloadable[time.Duration] { 444 ptr, exists := getOrCreatePointer( 445 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, 446 time.Duration(defaultValueInTimescaleUnits)*timeScale, orderedKeys..., 447 ) 448 if !exists { 449 c.registerDurationVar(defaultValueInTimescaleUnits, ptr, true, timeScale, func(v time.Duration) { 450 ptr.store(v) 451 }, orderedKeys...) 452 } 453 return ptr 454 } 455 456 func (c *Config) registerDurationVar( 457 defaultValueInTimescaleUnits int64, ptr any, isHotReloadable bool, timeScale time.Duration, 458 store func(time.Duration), orderedKeys ...string, 459 ) { 460 configVar := configValue{ 461 value: ptr, 462 multiplier: timeScale, 463 defaultValue: defaultValueInTimescaleUnits, 464 keys: orderedKeys, 465 } 466 467 if isHotReloadable { 468 c.hotReloadableConfigLock.Lock() 469 c.appendVarToConfigMaps(orderedKeys, &configVar) 470 c.hotReloadableConfigLock.Unlock() 471 } 472 473 for _, key := range orderedKeys { 474 if c.IsSet(key) { 475 store(c.GetDuration(key, defaultValueInTimescaleUnits, timeScale)) 476 return 477 } 478 } 479 store(time.Duration(defaultValueInTimescaleUnits) * timeScale) 480 } 481 482 // RegisterStringConfigVariable registers string config variable 483 // 484 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 485 // e.g. asking for the same keys but in a different order can result in a different value to be returned 486 // 487 // Deprecated: use GetStringVar or GetReloadableStringVar instead 488 func RegisterStringConfigVariable(defaultValue string, ptr *string, isHotReloadable bool, orderedKeys ...string) { 489 Default.RegisterStringConfigVariable(defaultValue, ptr, isHotReloadable, orderedKeys...) 490 } 491 492 // GetStringVar registers a not hot-reloadable string config variable 493 // 494 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 495 // e.g. asking for the same keys but in a different order can result in a different value to be returned 496 func GetStringVar(defaultValue string, orderedKeys ...string) string { 497 return Default.GetStringVar(defaultValue, orderedKeys...) 498 } 499 500 // GetReloadableStringVar registers a hot-reloadable string config variable 501 // 502 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 503 // e.g. asking for the same keys but in a different order can result in a different value to be returned 504 func GetReloadableStringVar(defaultValue string, orderedKeys ...string) *Reloadable[string] { 505 return Default.GetReloadableStringVar(defaultValue, orderedKeys...) 506 } 507 508 // RegisterStringConfigVariable registers string config variable 509 // 510 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 511 // e.g. asking for the same keys but in a different order can result in a different value to be returned 512 // 513 // Deprecated: use GetStringVar or GetReloadableStringVar instead 514 func (c *Config) RegisterStringConfigVariable( 515 defaultValue string, ptr *string, isHotReloadable bool, orderedKeys ...string, 516 ) { 517 c.registerStringVar(defaultValue, ptr, isHotReloadable, func(v string) { 518 *ptr = v 519 }, orderedKeys...) 520 } 521 522 // GetStringVar registers a not hot-reloadable string config variable 523 // 524 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 525 // e.g. asking for the same keys but in a different order can result in a different value to be returned 526 func (c *Config) GetStringVar(defaultValue string, orderedKeys ...string) string { 527 var ret string 528 c.registerStringVar(defaultValue, nil, false, func(v string) { 529 ret = v 530 }, orderedKeys...) 531 return ret 532 } 533 534 // GetReloadableStringVar registers a hot-reloadable string config variable 535 // 536 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 537 // e.g. asking for the same keys but in a different order can result in a different value to be returned 538 func (c *Config) GetReloadableStringVar(defaultValue string, orderedKeys ...string) *Reloadable[string] { 539 ptr, exists := getOrCreatePointer( 540 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, defaultValue, orderedKeys..., 541 ) 542 if !exists { 543 c.registerStringVar(defaultValue, ptr, true, func(v string) { 544 ptr.store(v) 545 }, orderedKeys...) 546 } 547 return ptr 548 } 549 550 func (c *Config) registerStringVar( 551 defaultValue string, ptr any, isHotReloadable bool, store func(string), orderedKeys ...string, 552 ) { 553 configVar := configValue{ 554 value: ptr, 555 defaultValue: defaultValue, 556 keys: orderedKeys, 557 } 558 559 if isHotReloadable { 560 c.hotReloadableConfigLock.Lock() 561 c.appendVarToConfigMaps(orderedKeys, &configVar) 562 c.hotReloadableConfigLock.Unlock() 563 } 564 565 for _, key := range orderedKeys { 566 if c.IsSet(key) { 567 store(c.GetString(key, defaultValue)) 568 return 569 } 570 } 571 store(defaultValue) 572 } 573 574 // RegisterStringSliceConfigVariable registers string slice config variable 575 // 576 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 577 // e.g. asking for the same keys but in a different order can result in a different value to be returned 578 // 579 // Deprecated: use GetStringSliceVar or GetReloadableStringSliceVar instead 580 func RegisterStringSliceConfigVariable(defaultValue []string, ptr *[]string, isHotReloadable bool, orderedKeys ...string) { 581 Default.RegisterStringSliceConfigVariable(defaultValue, ptr, isHotReloadable, orderedKeys...) 582 } 583 584 // GetStringSliceVar registers a not hot-reloadable string slice config variable 585 // 586 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 587 // e.g. asking for the same keys but in a different order can result in a different value to be returned 588 func GetStringSliceVar(defaultValue []string, orderedKeys ...string) []string { 589 return Default.GetStringSliceVar(defaultValue, orderedKeys...) 590 } 591 592 // GetReloadableStringSliceVar registers a hot-reloadable string slice config variable 593 // 594 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 595 // e.g. asking for the same keys but in a different order can result in a different value to be returned 596 func GetReloadableStringSliceVar(defaultValue []string, orderedKeys ...string) *Reloadable[[]string] { 597 return Default.GetReloadableStringSliceVar(defaultValue, orderedKeys...) 598 } 599 600 // RegisterStringSliceConfigVariable registers string slice config variable 601 // 602 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 603 // e.g. asking for the same keys but in a different order can result in a different value to be returned 604 // 605 // Deprecated: use GetStringSliceVar or GetReloadableStringSliceVar instead 606 func (c *Config) RegisterStringSliceConfigVariable( 607 defaultValue []string, ptr *[]string, isHotReloadable bool, orderedKeys ...string, 608 ) { 609 c.registerStringSliceVar(defaultValue, ptr, isHotReloadable, func(v []string) { 610 *ptr = v 611 }, orderedKeys...) 612 } 613 614 // GetStringSliceVar registers a not hot-reloadable string slice config variable 615 // 616 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 617 // e.g. asking for the same keys but in a different order can result in a different value to be returned 618 func (c *Config) GetStringSliceVar(defaultValue []string, orderedKeys ...string) []string { 619 var ret []string 620 c.registerStringSliceVar(defaultValue, ret, false, func(v []string) { 621 ret = v 622 }, orderedKeys...) 623 return ret 624 } 625 626 // GetReloadableStringSliceVar registers a hot-reloadable string slice config variable 627 // 628 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 629 // e.g. asking for the same keys but in a different order can result in a different value to be returned 630 func (c *Config) GetReloadableStringSliceVar(defaultValue []string, orderedKeys ...string) *Reloadable[[]string] { 631 ptr, exists := getOrCreatePointer( 632 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, defaultValue, orderedKeys..., 633 ) 634 if !exists { 635 c.registerStringSliceVar(defaultValue, ptr, true, func(v []string) { 636 ptr.store(v) 637 }, orderedKeys...) 638 } 639 return ptr 640 } 641 642 func (c *Config) registerStringSliceVar( 643 defaultValue []string, ptr any, isHotReloadable bool, store func([]string), orderedKeys ...string, 644 ) { 645 configVar := configValue{ 646 value: ptr, 647 defaultValue: defaultValue, 648 keys: orderedKeys, 649 } 650 651 if isHotReloadable { 652 c.hotReloadableConfigLock.Lock() 653 c.appendVarToConfigMaps(orderedKeys, &configVar) 654 c.hotReloadableConfigLock.Unlock() 655 } 656 657 for _, key := range orderedKeys { 658 if c.IsSet(key) { 659 store(c.GetStringSlice(key, defaultValue)) 660 return 661 } 662 } 663 store(defaultValue) 664 } 665 666 // RegisterStringMapConfigVariable registers string map config variable 667 // 668 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 669 // e.g. asking for the same keys but in a different order can result in a different value to be returned 670 // 671 // Deprecated: use GetStringMapVar or GetReloadableStringMapVar instead 672 func RegisterStringMapConfigVariable( 673 defaultValue map[string]interface{}, ptr *map[string]interface{}, isHotReloadable bool, orderedKeys ...string, 674 ) { 675 Default.RegisterStringMapConfigVariable(defaultValue, ptr, isHotReloadable, orderedKeys...) 676 } 677 678 // GetStringMapVar registers a not hot-reloadable string map config variable 679 // 680 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 681 // e.g. asking for the same keys but in a different order can result in a different value to be returned 682 func GetStringMapVar(defaultValue map[string]interface{}, orderedKeys ...string) map[string]interface{} { 683 return Default.GetStringMapVar(defaultValue, orderedKeys...) 684 } 685 686 // GetReloadableStringMapVar registers a hot-reloadable string map config variable 687 // 688 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 689 // e.g. asking for the same keys but in a different order can result in a different value to be returned 690 func GetReloadableStringMapVar( 691 defaultValue map[string]interface{}, orderedKeys ...string, 692 ) *Reloadable[map[string]interface{}] { 693 return Default.GetReloadableStringMapVar(defaultValue, orderedKeys...) 694 } 695 696 // RegisterStringMapConfigVariable registers string map config variable 697 // 698 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 699 // e.g. asking for the same keys but in a different order can result in a different value to be returned 700 // 701 // Deprecated: use GetStringMapVar or GetReloadableStringMapVar instead 702 func (c *Config) RegisterStringMapConfigVariable( 703 defaultValue map[string]interface{}, ptr *map[string]interface{}, isHotReloadable bool, orderedKeys ...string, 704 ) { 705 c.registerStringMapVar(defaultValue, ptr, isHotReloadable, func(v map[string]interface{}) { 706 *ptr = v 707 }, orderedKeys...) 708 } 709 710 // GetStringMapVar registers a not hot-reloadable string map config variable 711 // 712 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 713 // e.g. asking for the same keys but in a different order can result in a different value to be returned 714 func (c *Config) GetStringMapVar( 715 defaultValue map[string]interface{}, orderedKeys ...string, 716 ) map[string]interface{} { 717 var ret map[string]interface{} 718 c.registerStringMapVar(defaultValue, nil, false, func(v map[string]interface{}) { 719 ret = v 720 }, orderedKeys...) 721 return ret 722 } 723 724 // GetReloadableStringMapVar registers a hot-reloadable string map config variable 725 // 726 // WARNING: keys are being looked up in requested order and the value of the first found key is returned, 727 // e.g. asking for the same keys but in a different order can result in a different value to be returned 728 func (c *Config) GetReloadableStringMapVar( 729 defaultValue map[string]interface{}, orderedKeys ...string, 730 ) *Reloadable[map[string]interface{}] { 731 ptr, exists := getOrCreatePointer( 732 c.reloadableVars, c.reloadableVarsMisuses, &c.reloadableVarsLock, defaultValue, orderedKeys..., 733 ) 734 if !exists { 735 c.registerStringMapVar(defaultValue, ptr, true, func(v map[string]interface{}) { 736 ptr.store(v) 737 }, orderedKeys...) 738 } 739 return ptr 740 } 741 742 func (c *Config) registerStringMapVar( 743 defaultValue map[string]interface{}, ptr any, isHotReloadable bool, store func(map[string]interface{}), orderedKeys ...string, 744 ) { 745 configVar := configValue{ 746 value: ptr, 747 defaultValue: defaultValue, 748 keys: orderedKeys, 749 } 750 751 if isHotReloadable { 752 c.hotReloadableConfigLock.Lock() 753 c.appendVarToConfigMaps(orderedKeys, &configVar) 754 c.hotReloadableConfigLock.Unlock() 755 } 756 757 for _, key := range orderedKeys { 758 if c.IsSet(key) { 759 store(c.GetStringMap(key, defaultValue)) 760 return 761 } 762 } 763 store(defaultValue) 764 } 765 766 func (c *Config) appendVarToConfigMaps(keys []string, configVar *configValue) { 767 key := strings.Join(keys, ",") 768 if _, ok := c.hotReloadableConfig[key]; !ok { 769 c.hotReloadableConfig[key] = make([]*configValue, 0) 770 } 771 c.hotReloadableConfig[key] = append(c.hotReloadableConfig[key], configVar) 772 } 773 774 type configTypes interface { 775 int | int64 | string | time.Duration | bool | float64 | []string | map[string]interface{} 776 } 777 778 // Reloadable is used as a wrapper for hot-reloadable config variables 779 type Reloadable[T configTypes] struct { 780 value T 781 lock sync.RWMutex 782 } 783 784 // Load should be used to read the underlying value without worrying about data races 785 func (a *Reloadable[T]) Load() T { 786 a.lock.RLock() 787 v := a.value 788 a.lock.RUnlock() 789 return v 790 } 791 792 func (a *Reloadable[T]) store(v T) { 793 a.lock.Lock() 794 a.value = v 795 a.lock.Unlock() 796 } 797 798 // swapIfNotEqual is used internally to swap the value of a hot-reloadable config variable 799 // if the new value is not equal to the old value 800 func (a *Reloadable[T]) swapIfNotEqual(new T, compare func(old, new T) bool) (old T, swapped bool) { 801 a.lock.Lock() 802 defer a.lock.Unlock() 803 if !compare(a.value, new) { 804 old := a.value 805 a.value = new 806 return old, true 807 } 808 return a.value, false 809 } 810 811 func compare[T comparable]() func(a, b T) bool { 812 return func(a, b T) bool { 813 return a == b 814 } 815 }