mirror of
https://github.com/spf13/viper
synced 2024-12-23 12:07:02 +00:00
Implement CancelWatchConfig which allows one to turn off the watcher
This commit is contained in:
parent
62edee3196
commit
c3ab84f775
3 changed files with 59 additions and 0 deletions
|
@ -123,6 +123,9 @@ viper.OnConfigChange(func(e fsnotify.Event) {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you wish to stop watching the configPaths, simply call viper.CancelWatchConfig().
|
||||||
|
Note: This might be necessary if your tests involve trying out various config files.
|
||||||
|
|
||||||
### Reading Config from io.Reader
|
### Reading Config from io.Reader
|
||||||
|
|
||||||
Viper predefines many configuration sources such as files, environment
|
Viper predefines many configuration sources such as files, environment
|
||||||
|
|
18
viper.go
18
viper.go
|
@ -202,6 +202,7 @@ type Viper struct {
|
||||||
properties *properties.Properties
|
properties *properties.Properties
|
||||||
|
|
||||||
onConfigChange func(fsnotify.Event)
|
onConfigChange func(fsnotify.Event)
|
||||||
|
watchConfigCancel func() (waiter func())
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns an initialized Viper instance.
|
// New returns an initialized Viper instance.
|
||||||
|
@ -300,6 +301,13 @@ func (v *Viper) WatchConfig() {
|
||||||
|
|
||||||
eventsWG := sync.WaitGroup{}
|
eventsWG := sync.WaitGroup{}
|
||||||
eventsWG.Add(1)
|
eventsWG.Add(1)
|
||||||
|
v.watchConfigCancel = func() (waiter func()) {
|
||||||
|
watcher.Close()
|
||||||
|
v.watchConfigCancel = nil
|
||||||
|
return func() {
|
||||||
|
eventsWG.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -346,6 +354,16 @@ func (v *Viper) WatchConfig() {
|
||||||
initWG.Wait() // make sure that the go routine above fully ended before returning
|
initWG.Wait() // make sure that the go routine above fully ended before returning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CancelWatchConfig() (future func()) {
|
||||||
|
return v.CancelWatchConfig()
|
||||||
|
}
|
||||||
|
func (v *Viper) CancelWatchConfig() (future func()) {
|
||||||
|
if v.watchConfigCancel != nil {
|
||||||
|
return v.watchConfigCancel()
|
||||||
|
}
|
||||||
|
return func(){}
|
||||||
|
}
|
||||||
|
|
||||||
// SetConfigFile explicitly defines the path, name and extension of the config file.
|
// SetConfigFile explicitly defines the path, name and extension of the config file.
|
||||||
// Viper will use this and not check any of the config paths.
|
// Viper will use this and not check any of the config paths.
|
||||||
func SetConfigFile(in string) { v.SetConfigFile(in) }
|
func SetConfigFile(in string) { v.SetConfigFile(in) }
|
||||||
|
|
|
@ -1510,6 +1510,44 @@ func TestWatchFile(t *testing.T) {
|
||||||
assert.Equal(t, "baz", v.Get("foo"))
|
assert.Equal(t, "baz", v.Get("foo"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("file content changed after cancel", func(t *testing.T) {
|
||||||
|
// given a `config.yaml` file being watched
|
||||||
|
v, configFile, cleanup := newViperWithConfigFile(t)
|
||||||
|
defer cleanup()
|
||||||
|
_, err := os.Stat(configFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Logf("test config file: %s\n", configFile)
|
||||||
|
|
||||||
|
// first run through with watching enabled
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
wg.Add(1)
|
||||||
|
v.OnConfigChange(func(in fsnotify.Event) {
|
||||||
|
t.Logf("WatchConfig saw first config change")
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
v.WatchConfig()
|
||||||
|
// when overwriting the file and waiting for the custom change notification handler to be triggered
|
||||||
|
err = ioutil.WriteFile(configFile, []byte("foo: baz\n"), 0640)
|
||||||
|
wg.Wait()
|
||||||
|
// then the config value should have changed
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, "baz", v.Get("foo"))
|
||||||
|
|
||||||
|
// cancel and wait for the canceling to finish.
|
||||||
|
waitForCancel := v.CancelWatchConfig()
|
||||||
|
v.OnConfigChange(func(in fsnotify.Event) {
|
||||||
|
t.Error("CancelWatchConfig did not prevent second change from being seen.")
|
||||||
|
})
|
||||||
|
waitForCancel()
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(configFile, []byte("foo: quz\n"), 0640)
|
||||||
|
// We need to sleep a bit here because there isn't any signal of use for this invisible write.
|
||||||
|
time.Sleep(30 * time.Millisecond)
|
||||||
|
|
||||||
|
// the config value should still be the same.
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, "baz", v.Get("foo"), "CancelWatchConfig did not prevent second change from being seen.")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkGetBool(b *testing.B) {
|
func BenchmarkGetBool(b *testing.B) {
|
||||||
|
|
Loading…
Reference in a new issue