7.3 KiB
7.3 KiB
Config Package Architecture
Overview
The lixenwraith/config package provides thread-safe configuration management with support for multiple sources, type-safe struct population, and live reconfiguration.
Logical Architecture
┌──────────────────────────────────────────────────────────┐
│ User API Layer │
├────────────────┬────────────────┬────────────────────────┤
│ Builder │ Type-Safe │ Dynamic Access │
│ Pattern │ Struct API │ Key-Value API │
├────────────────┴────────────────┴────────────────────────┤
│ Core Config Engine │
│ • Path Registration • Source Merging • Thread Safety │
├──────────────────────────────────────────────────────────┤
│ Source Loaders │
│ File │ Environment │ CLI Arguments │ Defaults │
├──────────────────────────────────────────────────────────┤
│ Supporting Systems │
│ Validation │ Type Decode │ File Watch │ Error Handling │
└──────────────────────────────────────────────────────────┘
Component Interactions
Builder Flow:
NewBuilder()
↓
Configure (WithTarget, WithFile, WithEnvPrefix)
↓
Build() → Register Paths → Load Sources → Merge Values
↓
Config Instance
↓
AsStruct() / Get() / Watch()
Value Resolution:
Path Request
↓
Check Registration
↓
Search Sources (CLI → Env → File → Default)
↓
Type Conversion
↓
Return Value
Live Reload:
File Change Detected
↓
Debounce Timer
↓
Reload File
↓
Merge with Sources
↓
Notify Watchers
File Organization
Core (config.go)
- Config struct: Thread-safe state management with atomic versioning
- Initialization:
New(),NewWithOptions() - State Management:
Get(),Set(),GetSource(),SetSource() - Precedence Control:
SetPrecedence(),GetPrecedence(),computeValue() - Cache Management:
AsStruct(),populateStruct(),invalidateCache() - Source Operations:
Reset(),ResetSource(),GetSources()
Registration (register.go)
- Path Registration:
Register(),RegisterWithEnv(),RegisterRequired(),Unregister() - Struct Registration:
RegisterStruct(),RegisterStructWithTags(),registerFields() - Discovery:
GetRegisteredPaths(),GetRegisteredPathsWithDefaults() - Decoding Bridge:
Scan(),ScanSource()- delegates to decode.go
Builder Pattern (builder.go)
- Fluent API:
NewBuilder(),Build(),MustBuild() - Configuration:
WithTarget(),WithDefaults(),WithFile(),WithEnvPrefix() - Discovery Integration:
WithFileDiscovery() - Validation:
WithValidator(),WithTypedValidator() - Security:
WithSecurityOptions()
Source Loading (loader.go)
- Multi-Source Loading:
loadWithOptions() - Individual Sources:
LoadFile(),LoadEnv(),LoadCLI() - Persistence:
Save(),SaveSource(),atomicWriteFile() - Environment Mapping:
DiscoverEnv(),ExportEnv(),defaultEnvTransform() - Parsing:
parseArgs(),parseValue(),detectFileFormat() - Security Checks: Path traversal, file ownership, size limits
Type System (decode.go)
- Unified Decoding:
unmarshal()- single authoritative decoder - Hook Composition:
getDecodeHook(),customDecodeHook() - Type Converters:
jsonNumberHookFunc(),stringToNetIPHookFunc(),stringToURLHookFunc() - Navigation:
navigateToPath(),normalizeMap()
File Watching (watch.go)
- Auto-Reload:
AutoUpdate(),AutoUpdateWithOptions(),StopAutoUpdate() - Subscriptions:
Watch(),WatchWithOptions(),WatchFile() - Watcher State:
watcherstruct with debouncing, polling, version tracking - Change Detection:
checkAndReload(),performReload(),notifyWatchers() - Resource Management: Max watcher limits, graceful shutdown
Convenience API (utility.go)
- Quick Setup:
Quick(),QuickCustom(),MustQuick(),QuickTyped() - Flag Integration:
GenerateFlags(),BindFlags() - Type-Safe Access:
GetTyped(),GetTypedWithDefault(),ScanTyped() - Utilities:
Validate(),Debug(),Dump(),Clone(),ScanMap()
File Discovery (discovery.go)
- Options:
FileDiscoveryOptionsstruct with search strategies - XDG Compliance:
getXDGConfigPaths()for standard config locations - Defaults:
DefaultDiscoveryOptions()with sensible patterns
Validation Library (validator.go)
- Network:
Port(),IPAddress(),IPv4Address(),IPv6Address() - Numeric:
Positive(),NonNegative(),Range() - String:
NonEmpty(),Pattern(),OneOf(),URLPath()
Error System (error.go)
- Categories: Sentinel errors for
errors.Is()checking - Wrapping:
wrapError()maintains dual error chains
Internal Utilities (helper.go)
- Map Operations:
flattenMap(),setNestedValue() - Validation:
isValidKeySegment()for path validation
Constants (constant.go)
- Shared Constants: Defines shared constants for timing, formats, limits, file watcher and discovery.
Data Flow Patterns
Configuration Loading
- Registration Phase: Paths registered with types/defaults
- Source Collection: Each source populates its layer
- Merge Phase: Precedence determines final values
- Population Phase: Struct populated via reflection
Thread Safety Model
- Read Operations: Multiple concurrent readers via RLock
- Write Operations: Exclusive access via Lock
- Atomic Updates: Prepare → Lock → Swap → Unlock pattern
- Version Tracking: Atomic counter for cache invalidation
Error Propagation
- Wrapped Errors: Category + specific error detail
- Early Return: Builder accumulates first error
- Panic Mode: MustBuild for fail-fast scenarios
Extension Points
Custom Types
Implement decode hooks in customDecodeHook():
func(f reflect.Type, t reflect.Type, data any) (any, error)
Source Transformation
Environment variable mapping via WithEnvTransform():
func(path string) string // Return env var name
Validation Layers
- Pre-decode:
WithValidator(func(*Config) error) - Post-decode:
WithTypedValidator(func(*YourType) error)
File Discovery
Search strategy via WithFileDiscovery():
- CLI flag check → Env var → XDG paths → Current dir