diff --git a/service/pkg/config/config.go b/service/pkg/config/config.go index aac79e7fbc..15e7d782bb 100644 --- a/service/pkg/config/config.go +++ b/service/pkg/config/config.go @@ -176,7 +176,13 @@ func (c *Config) WatchWithNamespaces(ctx context.Context, namespaces []Namespace // Now call the user-provided hooks with the new configuration. return c.OnChange(ctx) } - if err := loader.Watch(ctx, c, onChangeCallback, namespaces); err != nil { + if nsLoader, ok := loader.(NamespaceAwareLoader); ok { + if err := nsLoader.WatchWithNamespaces(ctx, c, onChangeCallback, namespaces); err != nil { + return err + } + continue + } + if err := loader.Watch(ctx, c, onChangeCallback); err != nil { return err } } diff --git a/service/pkg/config/config_file_loader.go b/service/pkg/config/config_file_loader.go index aec09c4937..06db0be3fa 100644 --- a/service/pkg/config/config_file_loader.go +++ b/service/pkg/config/config_file_loader.go @@ -63,7 +63,7 @@ func (l *FileLoader) Load(_ Config) error { } // Watch starts watching the config file for configuration changes -func (l *FileLoader) Watch(ctx context.Context, _ *Config, onChange func(context.Context) error, _ []NamespaceInfo) error { +func (l *FileLoader) Watch(ctx context.Context, _ *Config, onChange func(context.Context) error) error { l.viper.WatchConfig() // If config changes, trigger the main config reload function diff --git a/service/pkg/config/config_test.go b/service/pkg/config/config_test.go index 4ce51adc42..b5704a680b 100644 --- a/service/pkg/config/config_test.go +++ b/service/pkg/config/config_test.go @@ -19,7 +19,7 @@ type MockLoader struct { loadFn func(Config) error getFn func(string) (any, error) getConfigKeysFn func() ([]string, error) - watchFn func(context.Context, *Config, func(context.Context) error, []NamespaceInfo) error + watchFn func(context.Context, *Config, func(context.Context) error) error closeFn func() error getNameFn func() string @@ -30,6 +30,23 @@ type MockLoader struct { onChangeCalled bool } +// MockNamespaceAwareLoader extends MockLoader with NamespaceAwareLoader support +type MockNamespaceAwareLoader struct { + MockLoader + watchWithNamespacesFn func(context.Context, *Config, func(context.Context) error, []NamespaceInfo) error +} + +func (l *MockNamespaceAwareLoader) WatchWithNamespaces(ctx context.Context, config *Config, onChange func(context.Context) error, namespaces []NamespaceInfo) error { + l.watchCalled = true + if l.watchWithNamespacesFn != nil { + if err := l.watchWithNamespacesFn(ctx, config, onChange, namespaces); err != nil { + return err + } + l.onChangeCalled = true + } + return nil +} + func (l *MockLoader) Load(mostRecentConfig Config) error { if l.loadFn != nil { return l.loadFn(mostRecentConfig) @@ -51,10 +68,10 @@ func (l *MockLoader) GetConfigKeys() ([]string, error) { return nil, nil } -func (l *MockLoader) Watch(ctx context.Context, config *Config, onChange func(context.Context) error, namespaces []NamespaceInfo) error { +func (l *MockLoader) Watch(ctx context.Context, config *Config, onChange func(context.Context) error) error { l.watchCalled = true if l.watchFn != nil { - if err := l.watchFn(ctx, config, onChange, namespaces); err != nil { + if err := l.watchFn(ctx, config, onChange); err != nil { return err } l.onChangeCalled = true @@ -123,7 +140,7 @@ func TestConfig_Watch(t *testing.T) { config := &Config{} loader := newMockLoader() // Mock loader to call onChange - loader.watchFn = func(_ context.Context, _ *Config, _ func(context.Context) error, _ []NamespaceInfo) error { + loader.watchFn = func(_ context.Context, _ *Config, _ func(context.Context) error) error { return nil } config.AddLoader(loader) @@ -139,7 +156,7 @@ func TestConfig_Watch(t *testing.T) { config := &Config{} expectedErr := errors.New("watch error") loader := newMockLoader() - loader.watchFn = func(_ context.Context, _ *Config, _ func(context.Context) error, _ []NamespaceInfo) error { + loader.watchFn = func(_ context.Context, _ *Config, _ func(context.Context) error) error { return expectedErr } config.AddLoader(loader) @@ -153,7 +170,7 @@ func TestConfig_Watch(t *testing.T) { t.Run("Loader receives NamespaceInfo", func(t *testing.T) { config := &Config{} - loader := newMockLoader() + loader := &MockNamespaceAwareLoader{} testNamespaces := []NamespaceInfo{ { Name: "test-ns", @@ -165,7 +182,7 @@ func TestConfig_Watch(t *testing.T) { } var receivedNamespaces []NamespaceInfo - loader.watchFn = func(_ context.Context, _ *Config, _ func(context.Context) error, namespaces []NamespaceInfo) error { + loader.watchWithNamespacesFn = func(_ context.Context, _ *Config, _ func(context.Context) error, namespaces []NamespaceInfo) error { receivedNamespaces = namespaces return nil } diff --git a/service/pkg/config/default_settings_loader.go b/service/pkg/config/default_settings_loader.go index 9d93a46ce9..392959d802 100644 --- a/service/pkg/config/default_settings_loader.go +++ b/service/pkg/config/default_settings_loader.go @@ -90,7 +90,7 @@ func (l *DefaultSettingsLoader) Load(_ Config) error { return nil } -func (l *DefaultSettingsLoader) Watch(_ context.Context, _ *Config, _ func(context.Context) error, _ []NamespaceInfo) error { +func (l *DefaultSettingsLoader) Watch(_ context.Context, _ *Config, _ func(context.Context) error) error { return nil } diff --git a/service/pkg/config/environment_value_loader.go b/service/pkg/config/environment_value_loader.go index 741fb97d8b..d2821362c7 100644 --- a/service/pkg/config/environment_value_loader.go +++ b/service/pkg/config/environment_value_loader.go @@ -95,7 +95,7 @@ func (l *EnvironmentValueLoader) Load(_ Config) error { } // Watch starts watching the config file for configuration changes -func (l *EnvironmentValueLoader) Watch(_ context.Context, _ *Config, _ func(context.Context) error, _ []NamespaceInfo) error { +func (l *EnvironmentValueLoader) Watch(_ context.Context, _ *Config, _ func(context.Context) error) error { // Environment variables can't be watched. return nil } diff --git a/service/pkg/config/legacy_loader.go b/service/pkg/config/legacy_loader.go index a9c2ff5a50..6c5f651a4f 100644 --- a/service/pkg/config/legacy_loader.go +++ b/service/pkg/config/legacy_loader.go @@ -75,7 +75,7 @@ func (l *LegacyLoader) Load(cfg Config) error { } // Watch starts watching the config file for configuration changes -func (l *LegacyLoader) Watch(ctx context.Context, _ *Config, onChange func(context.Context) error, _ []NamespaceInfo) error { +func (l *LegacyLoader) Watch(ctx context.Context, _ *Config, onChange func(context.Context) error) error { l.viper.WatchConfig() // If config changes, trigger the main config reload function diff --git a/service/pkg/config/loader.go b/service/pkg/config/loader.go index 14ac7bc0ea..cbd13c33d9 100644 --- a/service/pkg/config/loader.go +++ b/service/pkg/config/loader.go @@ -26,11 +26,19 @@ type Loader interface { // Load is called to load/refresh the configuration from its source Load(mostRecentConfig Config) error // Watch starts watching for configuration changes and invokes an onChange callback. - // It receives information about the registered namespaces and services to determine - // if watching is required for this loader. - Watch(ctx context.Context, cfg *Config, onChange func(context.Context) error, namespaces []NamespaceInfo) error + Watch(ctx context.Context, cfg *Config, onChange func(context.Context) error) error // Close closes the configuration loader Close() error // Name returns the name of the configuration loader Name() string } + +// NamespaceAwareLoader extends Loader with namespace-aware watching. +// Loaders that need information about registered namespaces and services +// should implement this interface. +type NamespaceAwareLoader interface { + Loader + // WatchWithNamespaces starts watching for configuration changes with + // information about the registered namespaces and services. + WatchWithNamespaces(ctx context.Context, cfg *Config, onChange func(context.Context) error, namespaces []NamespaceInfo) error +}