fixes to extra-record file watcher (#2298)
* Fix excess error message during writes Fixes #2290 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * retry filewatcher on removed files This should handled if files are deleted and added again, and for rename scenarios. Fixes #2289 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * test more write and remove in filewatcher Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
5345f19693
commit
ccc895b4c6
2 changed files with 119 additions and 10 deletions
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/rs/zerolog/log"
|
||||
"tailscale.com/tailcfg"
|
||||
|
@ -83,12 +84,39 @@ func (e *ExtraRecordsMan) Run() {
|
|||
log.Error().Caller().Msgf("file watcher event channel closing")
|
||||
return
|
||||
}
|
||||
switch event.Op {
|
||||
case fsnotify.Create, fsnotify.Write, fsnotify.Chmod:
|
||||
log.Trace().Caller().Str("path", event.Name).Str("op", event.Op.String()).Msg("extra records received filewatch event")
|
||||
if event.Name != e.path {
|
||||
continue
|
||||
}
|
||||
e.updateRecords()
|
||||
|
||||
log.Trace().Caller().Str("path", event.Name).Str("op", event.Op.String()).Msg("extra records received filewatch event")
|
||||
if event.Name != e.path {
|
||||
continue
|
||||
// If a file is removed or renamed, fsnotify will loose track of it
|
||||
// and not watch it. We will therefore attempt to re-add it with a backoff.
|
||||
case fsnotify.Remove, fsnotify.Rename:
|
||||
err := backoff.Retry(func() error {
|
||||
if _, err := os.Stat(e.path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}, backoff.NewExponentialBackOff())
|
||||
|
||||
if err != nil {
|
||||
log.Error().Caller().Err(err).Msgf("extra records filewatcher retrying to find file after delete")
|
||||
continue
|
||||
}
|
||||
|
||||
err = e.watcher.Add(e.path)
|
||||
if err != nil {
|
||||
log.Error().Caller().Err(err).Msgf("extra records filewatcher re-adding file after delete failed, giving up.")
|
||||
return
|
||||
} else {
|
||||
log.Trace().Caller().Str("path", e.path).Msg("extra records file re-added after delete")
|
||||
e.updateRecords()
|
||||
}
|
||||
}
|
||||
e.updateRecords()
|
||||
|
||||
case err, ok := <-e.watcher.Errors:
|
||||
if !ok {
|
||||
|
@ -116,6 +144,11 @@ func (e *ExtraRecordsMan) updateRecords() {
|
|||
return
|
||||
}
|
||||
|
||||
// If there are no records, ignore the update.
|
||||
if records == nil {
|
||||
return
|
||||
}
|
||||
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
|
@ -143,6 +176,12 @@ func readExtraRecordsFromPath(path string) ([]tailcfg.DNSRecord, [32]byte, error
|
|||
return nil, [32]byte{}, fmt.Errorf("reading path: %s, err: %w", path, err)
|
||||
}
|
||||
|
||||
// If the read was triggered too fast, and the file is not complete, ignore the update
|
||||
// if the file is empty. A consecutive update will be triggered when the file is complete.
|
||||
if len(b) == 0 {
|
||||
return nil, [32]byte{}, nil
|
||||
}
|
||||
|
||||
var records []tailcfg.DNSRecord
|
||||
err = json.Unmarshal(b, &records)
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue