lib/model: Refactor folder health/error handling (fixes #6557) (#6558)

This commit is contained in:
Simon Frei 2020-04-21 10:15:59 +02:00 committed by GitHub
parent c63ca4f563
commit 6bbd24de12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 32 deletions

View File

@ -123,7 +123,7 @@ func (f *folder) serve(ctx context.Context) {
pullFailTimer := time.NewTimer(0) pullFailTimer := time.NewTimer(0)
<-pullFailTimer.C <-pullFailTimer.C
if f.FSWatcherEnabled && f.CheckHealth() == nil { if f.FSWatcherEnabled && f.getHealthErrorAndLoadIgnores() == nil {
f.startWatch() f.startWatch()
} }
@ -260,15 +260,17 @@ func (f *folder) Delay(next time.Duration) {
f.scanDelay <- next f.scanDelay <- next
} }
// CheckHealth checks the folder for common errors, updates the folder state func (f *folder) getHealthErrorAndLoadIgnores() error {
// and returns the current folder error, or nil if the folder is healthy. if err := f.getHealthErrorWithoutIgnores(); err != nil {
func (f *folder) CheckHealth() error { return err
err := f.getHealthError() }
f.setError(err) if err := f.ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
return err return errors.Wrap(err, "loading ignores")
}
return nil
} }
func (f *folder) getHealthError() error { func (f *folder) getHealthErrorWithoutIgnores() error {
// Check for folder errors, with the most serious and specific first and // Check for folder errors, with the most serious and specific first and
// generic ones like out of space on the home disk later. // generic ones like out of space on the home disk later.
@ -318,19 +320,15 @@ func (f *folder) pull() bool {
} }
func (f *folder) scanSubdirs(subDirs []string) error { func (f *folder) scanSubdirs(subDirs []string) error {
if err := f.getHealthError(); err != nil { oldHash := f.ignores.Hash()
err := f.getHealthErrorAndLoadIgnores()
f.setError(err)
if err != nil {
// If there is a health error we set it as the folder error. We do not // If there is a health error we set it as the folder error. We do not
// clear the folder error if there is no health error, as there might be // clear the folder error if there is no health error, as there might be
// an *other* folder error (failed to load ignores, for example). Hence // an *other* folder error (failed to load ignores, for example). Hence
// we do not use the CheckHealth() convenience function here. // we do not use the CheckHealth() convenience function here.
f.setError(err)
return err
}
oldHash := f.ignores.Hash()
if err := f.ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
err = errors.Wrap(err, "loading ignores")
f.setError(err)
return err return err
} }
@ -345,9 +343,6 @@ func (f *folder) scanSubdirs(subDirs []string) error {
} }
}() }()
// We've passed all health checks so now mark ourselves healthy and queued
// for scanning.
f.setError(nil)
f.setState(FolderScanWaiting) f.setState(FolderScanWaiting)
if err := f.ioLimiter.takeWithContext(f.ctx, 1); err != nil { if err := f.ioLimiter.takeWithContext(f.ctx, 1); err != nil {
@ -402,7 +397,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
}) })
batchFn := func(fs []protocol.FileInfo) error { batchFn := func(fs []protocol.FileInfo) error {
if err := f.CheckHealth(); err != nil { if err := f.getHealthErrorWithoutIgnores(); err != nil {
l.Debugf("Stopping scan of folder %s due to: %s", f.Description(), err) l.Debugf("Stopping scan of folder %s due to: %s", f.Description(), err)
return err return err
} }

View File

@ -140,11 +140,6 @@ func newSendReceiveFolder(model *model, fset *db.FileSet, ignores *ignore.Matche
// pull returns true if it manages to get all needed items from peers, i.e. get // pull returns true if it manages to get all needed items from peers, i.e. get
// the device in sync with the global state. // the device in sync with the global state.
func (f *sendReceiveFolder) pull() bool { func (f *sendReceiveFolder) pull() bool {
if err := f.CheckHealth(); err != nil {
l.Debugln("Skipping pull of", f.Description(), "due to folder error:", err)
return false
}
// Check if the ignore patterns changed. // Check if the ignore patterns changed.
oldHash := f.ignores.Hash() oldHash := f.ignores.Hash()
defer func() { defer func() {
@ -152,9 +147,10 @@ func (f *sendReceiveFolder) pull() bool {
f.ignoresUpdated() f.ignoresUpdated()
} }
}() }()
if err := f.ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) { err := f.getHealthErrorAndLoadIgnores()
err = errors.Wrap(err, "loading ignores") f.setError(err)
f.setError(err) if err != nil {
l.Debugln("Skipping pull of", f.Description(), "due to folder error:", err)
return false return false
} }

View File

@ -54,7 +54,6 @@ type service interface {
Scan(subs []string) error Scan(subs []string) error
Serve() Serve()
Stop() Stop()
CheckHealth() error
Errors() []FileError Errors() []FileError
WatchError() error WatchError() error
ForceRescan(file protocol.FileInfo) error ForceRescan(file protocol.FileInfo) error

View File

@ -2294,8 +2294,8 @@ func TestIssue2782(t *testing.T) {
m.fmut.Lock() m.fmut.Lock()
runner := m.folderRunners["default"] runner := m.folderRunners["default"]
m.fmut.Unlock() m.fmut.Unlock()
if err := runner.CheckHealth(); err != nil { if _, _, err := runner.getState(); err != nil {
t.Error("health check error:", err) t.Error("folder error:", err)
} }
} }