* lib/model, cmd/syncthing: Wait for folder restarts to complete (fixes #5233) This is the somewhat ugly - but on the other hand clear - fix for what is really a somewhat thorny issue. To avoid zombie folder runners a new mutex is introduced that protects the RestartFolder operation. I hate adding more mutexes but the alternatives I can think of are worse. The other part of it is that the POST /rest/system/config operation now waits for the config commit to complete. The point of this is that until the commit has completed we should not accept another config commit. If we did, we could end up with two separate RestartFolders queued in the background. While they are both correct, and will run without interfering with each other, we can't guarantee the order in which they will run. Thus it could happen that the newer config got committed first, and the older config commited after that, leaving us with the wrong config running. * test * wip * hax * hax * unflake test * per folder mutexes * paranoia * race
74 lines
1.7 KiB
Go
74 lines
1.7 KiB
Go
// Copyright (C) 2016 The Syncthing Authors.
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
package main
|
|
|
|
import (
|
|
"github.com/syncthing/syncthing/lib/config"
|
|
"github.com/syncthing/syncthing/lib/protocol"
|
|
"github.com/syncthing/syncthing/lib/util"
|
|
)
|
|
|
|
type mockedConfig struct {
|
|
gui config.GUIConfiguration
|
|
}
|
|
|
|
func (c *mockedConfig) GUI() config.GUIConfiguration {
|
|
return c.gui
|
|
}
|
|
|
|
func (c *mockedConfig) ListenAddresses() []string {
|
|
return nil
|
|
}
|
|
|
|
func (c *mockedConfig) LDAP() config.LDAPConfiguration {
|
|
return config.LDAPConfiguration{}
|
|
}
|
|
|
|
func (c *mockedConfig) RawCopy() config.Configuration {
|
|
cfg := config.Configuration{}
|
|
util.SetDefaults(&cfg.Options)
|
|
return cfg
|
|
}
|
|
|
|
func (c *mockedConfig) Options() config.OptionsConfiguration {
|
|
return config.OptionsConfiguration{}
|
|
}
|
|
|
|
func (c *mockedConfig) Replace(cfg config.Configuration) (config.Waiter, error) {
|
|
return noopWaiter{}, nil
|
|
}
|
|
|
|
func (c *mockedConfig) Subscribe(cm config.Committer) {}
|
|
|
|
func (c *mockedConfig) Folders() map[string]config.FolderConfiguration {
|
|
return nil
|
|
}
|
|
|
|
func (c *mockedConfig) Devices() map[protocol.DeviceID]config.DeviceConfiguration {
|
|
return nil
|
|
}
|
|
|
|
func (c *mockedConfig) SetDevice(config.DeviceConfiguration) (config.Waiter, error) {
|
|
return noopWaiter{}, nil
|
|
}
|
|
|
|
func (c *mockedConfig) SetDevices([]config.DeviceConfiguration) (config.Waiter, error) {
|
|
return noopWaiter{}, nil
|
|
}
|
|
|
|
func (c *mockedConfig) Save() error {
|
|
return nil
|
|
}
|
|
|
|
func (c *mockedConfig) RequiresRestart() bool {
|
|
return false
|
|
}
|
|
|
|
type noopWaiter struct{}
|
|
|
|
func (noopWaiter) Wait() {}
|