Merge pull request #908 from TomChv/fix/sync-channel-close
Solve sub build miss synchronous behavior
This commit is contained in:
commit
65de05ecb5
@ -170,9 +170,6 @@ func (c *Client) buildfn(ctx context.Context, st *state.State, env *environment.
|
|||||||
go catchOutput(buildCh)
|
go catchOutput(buildCh)
|
||||||
|
|
||||||
resp, err := c.c.Build(ctx, opts, "", func(ctx context.Context, gw bkgw.Client) (*bkgw.Result, error) {
|
resp, err := c.c.Build(ctx, opts, "", func(ctx context.Context, gw bkgw.Client) (*bkgw.Result, error) {
|
||||||
// Close events channel
|
|
||||||
defer close(eventsCh)
|
|
||||||
|
|
||||||
s := solver.New(solver.Opts{
|
s := solver.New(solver.Opts{
|
||||||
Control: c.c,
|
Control: c.c,
|
||||||
Gateway: gw,
|
Gateway: gw,
|
||||||
@ -182,6 +179,9 @@ func (c *Client) buildfn(ctx context.Context, st *state.State, env *environment.
|
|||||||
NoCache: c.cfg.NoCache,
|
NoCache: c.cfg.NoCache,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Close events channel
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
// Compute output overlay
|
// Compute output overlay
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
if err := fn(ctx, env, s); err != nil {
|
if err := fn(ctx, env, s); err != nil {
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
bk "github.com/moby/buildkit/client"
|
bk "github.com/moby/buildkit/client"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
@ -19,7 +20,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Solver struct {
|
type Solver struct {
|
||||||
opts Opts
|
opts Opts
|
||||||
|
eventsWg *sync.WaitGroup
|
||||||
|
closeCh chan *bk.SolveStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
@ -33,7 +36,9 @@ type Opts struct {
|
|||||||
|
|
||||||
func New(opts Opts) Solver {
|
func New(opts Opts) Solver {
|
||||||
return Solver{
|
return Solver{
|
||||||
opts: opts,
|
eventsWg: &sync.WaitGroup{},
|
||||||
|
closeCh: make(chan *bk.SolveStatus),
|
||||||
|
opts: opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +65,12 @@ func (s Solver) NoCache() bool {
|
|||||||
return s.opts.NoCache
|
return s.opts.NoCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Solver) Stop() {
|
||||||
|
close(s.closeCh)
|
||||||
|
s.eventsWg.Wait()
|
||||||
|
close(s.opts.Events)
|
||||||
|
}
|
||||||
|
|
||||||
func (s Solver) AddCredentials(target, username, secret string) {
|
func (s Solver) AddCredentials(target, username, secret string) {
|
||||||
s.opts.Auth.AddCredentials(target, username, secret)
|
s.opts.Auth.AddCredentials(target, username, secret)
|
||||||
}
|
}
|
||||||
@ -145,11 +156,30 @@ func (s Solver) Solve(ctx context.Context, st llb.State) (bkgw.Reference, error)
|
|||||||
return res.SingleRef()
|
return res.SingleRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Forward events from solver to the main events channel
|
||||||
|
// It creates a task in the solver waiting group to be
|
||||||
|
// sure that everything will be forward to the main channel
|
||||||
|
func (s Solver) forwardEvents(ch chan *bk.SolveStatus) {
|
||||||
|
s.eventsWg.Add(1)
|
||||||
|
defer s.eventsWg.Done()
|
||||||
|
|
||||||
|
for event := range ch {
|
||||||
|
s.opts.Events <- event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Export will export `st` to `output`
|
// Export will export `st` to `output`
|
||||||
// FIXME: this is currently impleneted as a hack, starting a new Build session
|
// FIXME: this is currently impleneted as a hack, starting a new Build session
|
||||||
// within buildkit from the Control API. Ideally the Gateway API should allow to
|
// within buildkit from the Control API. Ideally the Gateway API should allow to
|
||||||
// Export directly.
|
// Export directly.
|
||||||
func (s Solver) Export(ctx context.Context, st llb.State, img *dockerfile2llb.Image, output bk.ExportEntry) (*bk.SolveResponse, error) {
|
func (s Solver) Export(ctx context.Context, st llb.State, img *dockerfile2llb.Image, output bk.ExportEntry) (*bk.SolveResponse, error) {
|
||||||
|
// Check close event channel and return if we're already done with the main pipeline
|
||||||
|
select {
|
||||||
|
case <-s.closeCh:
|
||||||
|
return nil, context.Canceled
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
def, err := s.Marshal(ctx, st)
|
def, err := s.Marshal(ctx, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -168,11 +198,7 @@ func (s Solver) Export(ctx context.Context, st llb.State, img *dockerfile2llb.Im
|
|||||||
|
|
||||||
// Forward this build session events to the main events channel, for logging
|
// Forward this build session events to the main events channel, for logging
|
||||||
// purposes.
|
// purposes.
|
||||||
go func() {
|
go s.forwardEvents(ch)
|
||||||
for event := range ch {
|
|
||||||
s.opts.Events <- event
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return s.opts.Control.Build(ctx, opts, "", func(ctx context.Context, c bkgw.Client) (*bkgw.Result, error) {
|
return s.opts.Control.Build(ctx, opts, "", func(ctx context.Context, c bkgw.Client) (*bkgw.Result, error) {
|
||||||
res, err := c.Solve(ctx, bkgw.SolveRequest{
|
res, err := c.Solve(ctx, bkgw.SolveRequest{
|
||||||
|
Reference in New Issue
Block a user