draincloud-core/internal/config/static_provider/static_provider.go
2024-10-17 16:20:42 -04:00

124 lines
2.4 KiB
Go

package staticprovider
import (
"context"
"os"
"path/filepath"
"sync"
"git.optclblast.xyz/draincloud/draincloud-core/internal/config"
"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
var _ config.Provider = new(staticProvider)
type StaticProvider interface {
config.Provider
}
type staticProvider struct {
m sync.RWMutex
rawValues map[string]any
}
func (p *staticProvider) GetValue(ctx context.Context, key config.Key) config.Value {
p.m.RLock()
defer p.m.RUnlock()
rawVal, ok := p.rawValues[string(key)]
if !ok {
return config.EmptyValue{}
}
switch val := rawVal.(type) {
case int:
return config.IntValue{
Val: val,
}
case string:
return config.StringValue{
Val: val,
}
case float32:
return config.FloatValue{
Val: val,
}
default:
return config.EmptyValue{}
}
}
type newStaticProviderOptions struct {
configName string
configDirPath string
configFileType string
}
func mustDefaultNewStaticProviderOptions(ctx context.Context) *newStaticProviderOptions {
ex, err := os.Executable()
if err != nil {
logger.Fatal(ctx, "failed to get executable location", logger.Err(err))
}
exPath := filepath.Dir(ex)
return &newStaticProviderOptions{
configName: "config",
configDirPath: exPath,
configFileType: "yaml",
}
}
type NewStaticProviderOption func(o *newStaticProviderOptions)
func WithConfigDir(path string) NewStaticProviderOption {
return func(o *newStaticProviderOptions) {
o.configDirPath = path
}
}
func WithConfigType(t string) NewStaticProviderOption {
return func(o *newStaticProviderOptions) {
o.configFileType = t
}
}
func WithConfigName(name string) NewStaticProviderOption {
return func(o *newStaticProviderOptions) {
o.configName = name
}
}
func NewStaticProvider(
ctx context.Context,
opts ...NewStaticProviderOption,
) (*staticProvider, error) {
o := mustDefaultNewStaticProviderOptions(ctx)
for _, opt := range opts {
opt(o)
}
// TODO check if ile exists
provider := &staticProvider{
rawValues: make(map[string]any),
}
viper.SetConfigName(o.configName)
viper.SetConfigType(o.configFileType)
viper.AddConfigPath(o.configDirPath)
viper.WatchConfig()
viper.OnConfigChange(func(_ fsnotify.Event) {
provider.m.Lock()
defer provider.m.Unlock()
provider.rawValues = viper.AllSettings()
})
provider.rawValues = viper.AllSettings()
return provider, nil
}