From c9650fc7d5e3f5ecaf2169691682c6fd3a77f460 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sun, 6 Apr 2025 05:31:02 -0700 Subject: [PATCH] chore(model): delay starting a pull while there are incoming index updates (#10041) This adds a simple delay to the process for starting the pull, by default one second. In practice this means we're likely to wait for initial index transfer, or multiple messages sent as part of a larger change. This is better because we're more likely to have the whole change for the purpose of handling renames etc, and also it's more efficient to do one larger puller iteration instead of multiple while also processing changes. It does however introduce a certain amount of delay into the sync process, so it can be tuned down or turned off entirely. --- lib/config/config_test.go | 2 ++ lib/config/folderconfiguration.go | 1 + lib/model/folder.go | 13 +++++++++++++ lib/model/testutils_test.go | 1 + 4 files changed, 17 insertions(+) diff --git a/lib/config/config_test.go b/lib/config/config_test.go index 27a6d8546..daf50eb57 100644 --- a/lib/config/config_test.go +++ b/lib/config/config_test.go @@ -108,6 +108,7 @@ func TestDefaultValues(t *testing.T) { FSWatcherEnabled: true, FSWatcherDelayS: 10, IgnorePerms: false, + PullerDelayS: 1, AutoNormalize: true, MinDiskFree: size, Versioning: VersioningConfiguration{ @@ -184,6 +185,7 @@ func TestDeviceConfig(t *testing.T) { FSWatcherDelayS: 10, Copiers: 0, Hashers: 0, + PullerDelayS: 1, AutoNormalize: true, MinDiskFree: Size{1, "%"}, MaxConflicts: -1, diff --git a/lib/config/folderconfiguration.go b/lib/config/folderconfiguration.go index 1bfc898db..9d4876dde 100644 --- a/lib/config/folderconfiguration.go +++ b/lib/config/folderconfiguration.go @@ -68,6 +68,7 @@ type FolderConfiguration struct { IgnoreDelete bool `json:"ignoreDelete" xml:"ignoreDelete"` ScanProgressIntervalS int `json:"scanProgressIntervalS" xml:"scanProgressIntervalS"` PullerPauseS int `json:"pullerPauseS" xml:"pullerPauseS"` + PullerDelayS float64 `json:"pullerDelayS" xml:"pullerDelayS" default:"1"` MaxConflicts int `json:"maxConflicts" xml:"maxConflicts" default:"10"` DisableSparseFiles bool `json:"disableSparseFiles" xml:"disableSparseFiles"` DisableTempIndexes bool `json:"disableTempIndexes" xml:"disableTempIndexes"` diff --git a/lib/model/folder.go b/lib/model/folder.go index 05a5b1032..10f2ac40c 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -173,6 +173,8 @@ func (f *folder) Serve(ctx context.Context) error { } initialCompleted := f.initialScanFinished + pullTimer := time.NewTimer(0) + pullTimer.Stop() for { var err error @@ -183,6 +185,17 @@ func (f *folder) Serve(ctx context.Context) error { return nil case <-f.pullScheduled: + if f.PullerDelayS > 0 { + // Wait for incoming updates to settle before doing the + // actual pull + f.setState(FolderSyncWaiting) + pullTimer.Reset(time.Duration(float64(time.Second) * f.PullerDelayS)) + } else { + _, err = f.pull() + } + + case <-pullTimer.C: + f.setState(FolderIdle) _, err = f.pull() case <-f.pullFailTimer.C: diff --git a/lib/model/testutils_test.go b/lib/model/testutils_test.go index 7949bc617..8d6140ec5 100644 --- a/lib/model/testutils_test.go +++ b/lib/model/testutils_test.go @@ -103,6 +103,7 @@ func newDefaultCfgWrapper() (config.Wrapper, config.FolderConfiguration, context func newFolderConfig() config.FolderConfiguration { cfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", config.FilesystemTypeFake, rand.String(32)+"?content=true") cfg.FSWatcherEnabled = false + cfg.PullerDelayS = 0 cfg.Devices = append(cfg.Devices, config.FolderDeviceConfiguration{DeviceID: device1}) return cfg }