Skip to content

Commit

Permalink
Merge pull request #48 from izumin5210/izumin5210/parallel-build
Browse files Browse the repository at this point in the history
Build tools in parallel
  • Loading branch information
izumin5210 authored Mar 8, 2020
2 parents 0596bdd + c614d9f commit 2c0d232
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 4 deletions.
14 changes: 14 additions & 0 deletions cmd/gex/errors_go112.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// +build !go1.13

package main

import (
"github.com/izumin5210/gex/pkg/tool"
)

func asBuildErrors(err error) *tool.BuildErrors {
if errs, ok := err.(*tool.BuildErrors); ok {
return errs
}
return nil
}
17 changes: 17 additions & 0 deletions cmd/gex/errors_go113.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// +build go1.13

package main

import (
"errors"

"github.com/izumin5210/gex/pkg/tool"
)

func asBuildErrors(err error) *tool.BuildErrors {
var errs *tool.BuildErrors
if errors.As(err, &errs) {
return errs
}
return nil
}
7 changes: 7 additions & 0 deletions cmd/gex/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ func run() error {
printHelp(os.Stdout)
case flagBuild:
err = toolRepo.BuildAll(ctx)
if errs := asBuildErrors(err); errs != nil {
for _, err := range errs.Errs {
fmt.Fprintln(os.Stdout, err.Error())
}
return errors.New("failed to build tools")
}
return err
case flagInit:
err = toolRepo.Add(ctx, "github.com/izumin5210/gex/cmd/gex")
case flagRegen:
Expand Down
55 changes: 55 additions & 0 deletions pkg/tool/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package tool

import (
"fmt"
"strings"
"sync"
)

type BuildError struct {
Tool Tool
Err error
}

func (e *BuildError) Unwrap() error { return e.Err }

func (e *BuildError) Error() string {
return fmt.Sprintf("failed to build %s: %s", e.Tool.Name(), e.Err)
}

type BuildErrors struct {
sync.RWMutex
Errs []*BuildError
}

func (e *BuildErrors) Unwrap() error {
e.RLock()
defer e.RUnlock()

return e.Errs[0]
}

func (e *BuildErrors) Error() string {
e.RLock()
defer e.RUnlock()

var b strings.Builder
b.WriteString("failed to build ")
b.WriteString(e.Errs[0].Tool.Name())
if n := len(e.Errs); n > 1 {
b.WriteString(fmt.Sprintf(" (and %d tool(s))", n))
}
b.WriteString(": ")
b.WriteString(e.Errs[0].Err.Error())
return b.String()
}

func (e *BuildErrors) Append(t Tool, err error) {
e.Lock()
defer e.Unlock()
e.Errs = append(e.Errs, &BuildError{Tool: t, Err: err})
}

func (e *BuildErrors) Empty() bool {
return len(e.Errs) == 0
}
25 changes: 21 additions & 4 deletions pkg/tool/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tool
import (
"context"
"strings"
"sync"

"github.com/pkg/errors"

Expand Down Expand Up @@ -116,11 +117,27 @@ func (r *repositoryImpl) BuildAll(ctx context.Context) error {
return errors.WithStack(err)
}

var (
wg sync.WaitGroup
errs BuildErrors
)

for _, t := range m.Tools() {
_, err = r.Build(ctx, t)
if err != nil {
return errors.WithStack(err)
}
t := t
wg.Add(1)
go func() {
defer wg.Done()
_, err = r.Build(ctx, t)
if err != nil {
errs.Append(t, err)
}
}()
}

wg.Wait()

if !errs.Empty() {
return &errs
}

return nil
Expand Down

0 comments on commit 2c0d232

Please sign in to comment.