From b96e27e0e73db855da3863656e34bdced8b3f04e Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Tue, 3 Jan 2023 10:09:05 +0100 Subject: [PATCH 1/2] limit build concurrency according to --parallel Signed-off-by: Nicolas De Loof --- pkg/compose/build.go | 25 ++++++++++++++----------- pkg/compose/dependencies.go | 9 ++++++++- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/pkg/compose/build.go b/pkg/compose/build.go index 9056209cd0..c12c0e310c 100644 --- a/pkg/compose/build.go +++ b/pkg/compose/build.go @@ -51,14 +51,16 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti opts := map[string]build.Options{} args := flatten(options.Args.Resolve(envResolver(project.Environment))) - services, err := project.GetServices(options.Services...) - if err != nil { - return err - } - - for _, service := range services { + return InDependencyOrder(ctx, project, func(ctx context.Context, name string) error { + if len(options.Services) > 0 && !utils.Contains(options.Services, name) { + return nil + } + service, err := project.GetService(name) + if err != nil { + return err + } if service.Build == nil { - continue + return nil } imageName := api.GetImageNameOrDefault(service, project.Name) buildOptions, err := s.toBuildOptions(project, service, imageName, options.SSHs) @@ -91,10 +93,11 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti }} } opts[imageName] = buildOptions - } - - _, err = s.doBuild(ctx, project, opts, options.Progress) - return err + _, err = s.doBuild(ctx, project, opts, options.Progress) + return err + }, func(traversal *graphTraversal) { + traversal.maxConcurrency = s.maxConcurrency + }) } func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project, quietPull bool) error { diff --git a/pkg/compose/dependencies.go b/pkg/compose/dependencies.go index 18af8fba69..8a146ebf14 100644 --- a/pkg/compose/dependencies.go +++ b/pkg/compose/dependencies.go @@ -47,7 +47,8 @@ type graphTraversal struct { targetServiceStatus ServiceStatus adjacentServiceStatusToSkip ServiceStatus - visitorFn func(context.Context, string) error + visitorFn func(context.Context, string) error + maxConcurrency int } func upDirectionTraversal(visitorFn func(context.Context, string) error) *graphTraversal { @@ -79,6 +80,9 @@ func InDependencyOrder(ctx context.Context, project *types.Project, fn func(cont return err } t := upDirectionTraversal(fn) + for _, option := range options { + option(t) + } return t.visit(ctx, graph) } @@ -96,6 +100,9 @@ func (t *graphTraversal) visit(ctx context.Context, g *Graph) error { nodes := t.extremityNodesFn(g) eg, ctx := errgroup.WithContext(ctx) + if t.maxConcurrency > 0 { + eg.SetLimit(t.maxConcurrency) + } t.run(ctx, g, eg, nodes) return eg.Wait() From aa5cdf2bf9ae8b43183fb7aab56ebf3431033f24 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Wed, 4 Jan 2023 12:41:36 +0100 Subject: [PATCH 2/2] add support for COMPOSE_PARALLEL_LIMIT (parity with Compose v1) Signed-off-by: Nicolas De Loof --- cmd/compose/compose.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/compose/compose.go b/cmd/compose/compose.go index 04ada280bb..55846dfb37 100644 --- a/cmd/compose/compose.go +++ b/cmd/compose/compose.go @@ -22,6 +22,7 @@ import ( "os" "os/signal" "path/filepath" + "strconv" "strings" "syscall" @@ -324,6 +325,13 @@ func RootCommand(streams api.Streams, backend api.Service) *cobra.Command { //no return err } } + if v, ok := os.LookupEnv("COMPOSE_PARALLEL_LIMIT"); ok && !cmd.Flags().Changed("parallel") { + i, err := strconv.Atoi(v) + if err != nil { + return fmt.Errorf("COMPOSE_PARALLEL_LIMIT must be an integer (found: %q)", v) + } + parallel = i + } if parallel > 0 { backend.MaxConcurrency(parallel) }