Merge pull request #10133 from ndeloof/build_concurrency

limit build concurrency according to --parallel
This commit is contained in:
Guillaume Lours 2023-01-05 09:57:13 +01:00 committed by GitHub
commit f6f29a4438
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 12 deletions

View File

@ -22,6 +22,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"syscall" "syscall"
@ -324,6 +325,13 @@ func RootCommand(streams api.Streams, backend api.Service) *cobra.Command { //no
return err 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 { if parallel > 0 {
backend.MaxConcurrency(parallel) backend.MaxConcurrency(parallel)
} }

View File

@ -51,14 +51,16 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
opts := map[string]build.Options{} opts := map[string]build.Options{}
args := flatten(options.Args.Resolve(envResolver(project.Environment))) args := flatten(options.Args.Resolve(envResolver(project.Environment)))
services, err := project.GetServices(options.Services...) return InDependencyOrder(ctx, project, func(ctx context.Context, name string) error {
if err != nil { if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
return err return nil
} }
service, err := project.GetService(name)
for _, service := range services { if err != nil {
return err
}
if service.Build == nil { if service.Build == nil {
continue return nil
} }
imageName := api.GetImageNameOrDefault(service, project.Name) imageName := api.GetImageNameOrDefault(service, project.Name)
buildOptions, err := s.toBuildOptions(project, service, imageName, options.SSHs) 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 opts[imageName] = buildOptions
} _, err = s.doBuild(ctx, project, opts, options.Progress)
return err
_, err = s.doBuild(ctx, project, opts, options.Progress) }, func(traversal *graphTraversal) {
return err traversal.maxConcurrency = s.maxConcurrency
})
} }
func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project, quietPull bool) error { func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project, quietPull bool) error {

View File

@ -47,7 +47,8 @@ type graphTraversal struct {
targetServiceStatus ServiceStatus targetServiceStatus ServiceStatus
adjacentServiceStatusToSkip 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 { 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 return err
} }
t := upDirectionTraversal(fn) t := upDirectionTraversal(fn)
for _, option := range options {
option(t)
}
return t.visit(ctx, graph) return t.visit(ctx, graph)
} }
@ -96,6 +100,9 @@ func (t *graphTraversal) visit(ctx context.Context, g *Graph) error {
nodes := t.extremityNodesFn(g) nodes := t.extremityNodesFn(g)
eg, ctx := errgroup.WithContext(ctx) eg, ctx := errgroup.WithContext(ctx)
if t.maxConcurrency > 0 {
eg.SetLimit(t.maxConcurrency)
}
t.run(ctx, g, eg, nodes) t.run(ctx, g, eg, nodes)
return eg.Wait() return eg.Wait()