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 }