瀏覽代碼

internal/sync: replace go-multierror.Group with golang.org/x/sync/errgroup

The go-multierror Group is just a shallow wrapper around sync.WaitGroup;
https://github.com/hashicorp/go-multierror/blob/v1.1.1/group.go#L5-L38

It does not limit concurrency, but handles synchronisation to collect
all errors (if any) in a go-multierror.

This patch replaces the go-multierror.Group for a sync.ErrGroup (which
is slightly easier to use, and does allow for limiting concurrency if
wanted), and a basic slice with mutex to collect the errors and to produce
a stdlib multi-error through errors.Join

Signed-off-by: Sebastiaan van Stijn <[email protected]>
Sebastiaan van Stijn 4 月之前
父節點
當前提交
93dd1a4558
共有 1 個文件被更改,包括 20 次插入7 次删除
  1. 20 7
      internal/sync/tar.go

+ 20 - 7
internal/sync/tar.go

@@ -29,11 +29,11 @@ import (
 	"path"
 	"path/filepath"
 	"strings"
-
-	"github.com/hashicorp/go-multierror"
+	"sync"
 
 	"github.com/docker/docker/api/types/container"
 	"github.com/moby/go-archive"
+	"golang.org/x/sync/errgroup"
 )
 
 type archiveEntry struct {
@@ -84,7 +84,14 @@ func (t *Tar) Sync(ctx context.Context, service string, paths []*PathMapping) er
 	if len(pathsToDelete) != 0 {
 		deleteCmd = append([]string{"rm", "-rf"}, pathsToDelete...)
 	}
-	var eg multierror.Group
+
+	var (
+		eg    errgroup.Group
+		errMu sync.Mutex
+		errs  = make([]error, 0, len(containers)*2) // max 2 errs per container
+	)
+
+	eg.SetLimit(16) // arbitrary limit, adjust to taste :D
 	for i := range containers {
 		containerID := containers[i].ID
 		tarReader := tarArchive(pathsToCopy)
@@ -92,17 +99,23 @@ func (t *Tar) Sync(ctx context.Context, service string, paths []*PathMapping) er
 		eg.Go(func() error {
 			if len(deleteCmd) != 0 {
 				if err := t.client.Exec(ctx, containerID, deleteCmd, nil); err != nil {
-					return fmt.Errorf("deleting paths in %s: %w", containerID, err)
+					errMu.Lock()
+					errs = append(errs, fmt.Errorf("deleting paths in %s: %w", containerID, err))
+					errMu.Unlock()
 				}
 			}
 
 			if err := t.client.Untar(ctx, containerID, tarReader); err != nil {
-				return fmt.Errorf("copying files to %s: %w", containerID, err)
+				errMu.Lock()
+				errs = append(errs, fmt.Errorf("copying files to %s: %w", containerID, err))
+				errMu.Unlock()
 			}
-			return nil
+			return nil // don't fail-fast; collect all errors
 		})
 	}
-	return eg.Wait().ErrorOrNil()
+
+	_ = eg.Wait()
+	return errors.Join(errs...)
 }
 
 type ArchiveBuilder struct {