From d43635d1d9361f38e48b7db50dae0fc888d381b7 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 5 Mar 2026 17:55:56 +0000 Subject: [PATCH] docker serve: restore volumes concurrently so one slow remote doesn't block others When restoring multiple volumes from saved state, each volume's filesystem setup (including connecting to the remote) was done sequentially. Now volumes are restored concurrently, so a single slow or unreachable remote doesn't delay the restoration of other volumes. --- cmd/serve/docker/driver.go | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/cmd/serve/docker/driver.go b/cmd/serve/docker/driver.go index ad0a420e8..8a4d3b9bb 100644 --- a/cmd/serve/docker/driver.go +++ b/cmd/serve/docker/driver.go @@ -361,17 +361,33 @@ func (drv *Driver) restoreState(ctx context.Context) error { return nil } - for _, vol := range state { - // Use a timeout so that a slow or unreachable remote does - // not block the plugin from starting up. - volCtx, cancel := context.WithTimeout(ctx, volTimeout) - err := vol.restoreState(volCtx, drv) - cancel() - if err != nil { - fs.Logf(nil, "Failed to restore volume %q: %v", vol.Name, err) + // Restore volumes concurrently so one slow remote doesn't + // block restoring the others. + type result struct { + vol *Volume + err error + } + results := make([]result, len(state)) + var wg sync.WaitGroup + for i, vol := range state { + wg.Add(1) + go func(i int, vol *Volume) { + defer wg.Done() + // Use a timeout so that a slow or unreachable remote does + // not block the plugin from starting up. + volCtx, cancel := context.WithTimeout(ctx, volTimeout) + defer cancel() + results[i] = result{vol: vol, err: vol.restoreState(volCtx, drv)} + }(i, vol) + } + wg.Wait() + + for _, r := range results { + if r.err != nil { + fs.Logf(nil, "Failed to restore volume %q: %v", r.vol.Name, r.err) continue } - drv.volumes[vol.Name] = vol + drv.volumes[r.vol.Name] = r.vol } return nil }