vfs/vfscache/downloaders: kick waiters periodically, not just once

The background kicker goroutine had a bare select outside a for loop,
so the 5s ticker fired at most once before the goroutine exited. The
intent was to run every 5s for the lifetime of the Downloaders.

This wraps the select in a for loop so the ticker fires repeatedly
until ctx is cancelled.

In practice this was benign because every downloader exit and every
successful Write already calls kickWaiters, so the background kicker
is only load-bearing when a waiter is queued, no downloader is
running, and _ensureDownloader failed transiently. In that state,
before this fix, the waiter would hang until another Download() call
or Close() arrived; now it gets retried every 5s and will either
recover or accumulate enough errors to trip maxErrorCount and error
out cleanly.
This commit is contained in:
Nick Craig-Wood
2026-04-24 18:12:44 +01:00
parent 7c56eff1a7
commit d2b8b73ea3

View File

@@ -117,16 +117,18 @@ func New(ctx context.Context, item Item, opt *vfscommon.Options, remote string,
}
dls.wg.Go(func() {
ticker := time.NewTicker(backgroundKickerInterval)
select {
case <-ticker.C:
err := dls.kickWaiters()
if err != nil {
fs.Errorf(dls.src, "vfs cache: failed to kick waiters: %v", err)
defer ticker.Stop()
for {
select {
case <-ticker.C:
err := dls.kickWaiters()
if err != nil {
fs.Errorf(dls.src, "vfs cache: failed to kick waiters: %v", err)
}
case <-ctx.Done():
return
}
case <-ctx.Done():
break
}
ticker.Stop()
})
return dls