From 9ce0df3242504cc7f2274d0c22b0730b1e26859c Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 14 Aug 2021 13:22:54 +0100 Subject: [PATCH] dropbox: add --dropbox-batch-commit-timeout to control batch timeout This also adds an Debug message log showing how long each batch took See: #5491 --- backend/dropbox/batcher.go | 22 +++++++++++++++------- backend/dropbox/dropbox.go | 24 +++++++++++++++--------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/backend/dropbox/batcher.go b/backend/dropbox/batcher.go index a4bc3bf0d..e662faca4 100644 --- a/backend/dropbox/batcher.go +++ b/backend/dropbox/batcher.go @@ -147,8 +147,14 @@ func (b *batcher) finishBatchJobStatus(ctx context.Context, launchBatchStatus *f } var batchStatus *files.UploadSessionFinishBatchJobStatus sleepTime := 100 * time.Millisecond - const maxTries = 120 - for try := 1; try <= maxTries; try++ { + const maxSleepTime = 1 * time.Second + startTime := time.Now() + try := 1 + for { + remaining := time.Duration(b.f.opt.BatchCommitTimeout) - time.Since(startTime) + if remaining < 0 { + break + } err = b.f.pacer.Call(func() (bool, error) { batchStatus, err = b.f.srv.UploadSessionFinishBatchCheck(&async.PollArg{ AsyncJobId: launchBatchStatus.AsyncJobId, @@ -156,23 +162,25 @@ func (b *batcher) finishBatchJobStatus(ctx context.Context, launchBatchStatus *f return shouldRetry(ctx, err) }) if err != nil { - fs.Debugf(b.f, "Wait for batch: sleeping for %v after error: %v: try %d/%d", sleepTime, err, try, maxTries) + fs.Debugf(b.f, "Wait for batch: sleeping for %v after error: %v: try %d remaining %v", sleepTime, err, try, remaining) } else { if batchStatus.Tag == "complete" { + fs.Debugf(b.f, "Upload batch completed in %v", time.Since(startTime)) return batchStatus.Complete, nil } - fs.Debugf(b.f, "Wait for batch: sleeping for %v after status: %q: try %d/%d", sleepTime, batchStatus.Tag, try, maxTries) + fs.Debugf(b.f, "Wait for batch: sleeping for %v after status: %q: try %d remaining %v", sleepTime, batchStatus.Tag, try, remaining) } time.Sleep(sleepTime) sleepTime *= 2 - if sleepTime > time.Second { - sleepTime = time.Second + if sleepTime > maxSleepTime { + sleepTime = maxSleepTime } + try++ } if err == nil { err = errors.New("batch didn't complete") } - return nil, errors.Wrapf(err, "wait for batch failed after %d tries", maxTries) + return nil, errors.Wrapf(err, "wait for batch failed after %d tries in %v", try, time.Since(startTime)) } // commit a batch diff --git a/backend/dropbox/dropbox.go b/backend/dropbox/dropbox.go index efcaa34f1..77274014a 100755 --- a/backend/dropbox/dropbox.go +++ b/backend/dropbox/dropbox.go @@ -266,6 +266,11 @@ default based on the batch_mode in use. `, Default: fs.Duration(0), Advanced: true, + }, { + Name: "batch_commit_timeout", + Help: `Max time to wait for a batch to finish comitting`, + Default: fs.Duration(10 * time.Minute), + Advanced: true, }, { Name: config.ConfigEncoding, Help: config.ConfigEncodingHelp, @@ -285,15 +290,16 @@ default based on the batch_mode in use. // Options defines the configuration for this backend type Options struct { - ChunkSize fs.SizeSuffix `config:"chunk_size"` - Impersonate string `config:"impersonate"` - SharedFiles bool `config:"shared_files"` - SharedFolders bool `config:"shared_folders"` - BatchMode string `config:"batch_mode"` - BatchSize int `config:"batch_size"` - BatchTimeout fs.Duration `config:"batch_timeout"` - AsyncBatch bool `config:"async_batch"` - Enc encoder.MultiEncoder `config:"encoding"` + ChunkSize fs.SizeSuffix `config:"chunk_size"` + Impersonate string `config:"impersonate"` + SharedFiles bool `config:"shared_files"` + SharedFolders bool `config:"shared_folders"` + BatchMode string `config:"batch_mode"` + BatchSize int `config:"batch_size"` + BatchTimeout fs.Duration `config:"batch_timeout"` + BatchCommitTimeout fs.Duration `config:"batch_commit_timeout"` + AsyncBatch bool `config:"async_batch"` + Enc encoder.MultiEncoder `config:"encoding"` } // Fs represents a remote dropbox server