@@ -3,6 +3,7 @@ package build
33import (
44 "context"
55 "fmt"
6+ "sync"
67
78 "github.com/containerd/containerd/platforms"
89 "github.com/docker/buildx/builder"
@@ -46,10 +47,22 @@ func (dp resolvedNode) BuildOpts(ctx context.Context) (gateway.BuildOpts, error)
4647
4748type matchMaker func (specs.Platform ) platforms.MatchComparer
4849
50+ type cachedGroup [T any ] struct {
51+ g flightcontrol.Group [T ]
52+ cache map [int ]T
53+ cacheMu sync.Mutex
54+ }
55+
56+ func newCachedGroup [T any ]() cachedGroup [T ] {
57+ return cachedGroup [T ]{
58+ cache : map [int ]T {},
59+ }
60+ }
61+
4962type nodeResolver struct {
50- nodes []builder.Node
51- clients flightcontrol. Group [* client.Client ]
52- opt flightcontrol. Group [gateway.BuildOpts ]
63+ nodes []builder.Node
64+ clients cachedGroup [* client.Client ]
65+ buildOpts cachedGroup [gateway.BuildOpts ]
5366}
5467
5568func resolveDrivers (ctx context.Context , nodes []builder.Node , opt map [string ]Options , pw progress.Writer ) (map [string ][]* resolvedNode , error ) {
@@ -63,7 +76,9 @@ func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]Op
6376
6477func newDriverResolver (nodes []builder.Node ) * nodeResolver {
6578 r := & nodeResolver {
66- nodes : nodes ,
79+ nodes : nodes ,
80+ clients : newCachedGroup [* client.Client ](),
81+ buildOpts : newCachedGroup [gateway.BuildOpts ](),
6782 }
6883 return r
6984}
@@ -179,6 +194,7 @@ func (r *nodeResolver) resolve(ctx context.Context, ps []specs.Platform, pw prog
179194 resolver : r ,
180195 driverIndex : 0 ,
181196 })
197+ nodeIdxs = append (nodeIdxs , 0 )
182198 } else {
183199 for i , idx := range nodeIdxs {
184200 node := & resolvedNode {
@@ -237,11 +253,24 @@ func (r *nodeResolver) boot(ctx context.Context, idxs []int, pw progress.Writer)
237253 for i , idx := range idxs {
238254 i , idx := i , idx
239255 eg .Go (func () error {
240- c , err := r .clients .Do (ctx , fmt .Sprint (idx ), func (ctx context.Context ) (* client.Client , error ) {
256+ c , err := r .clients .g . Do (ctx , fmt .Sprint (idx ), func (ctx context.Context ) (* client.Client , error ) {
241257 if r .nodes [idx ].Driver == nil {
242258 return nil , nil
243259 }
244- return driver .Boot (ctx , baseCtx , r .nodes [idx ].Driver , pw )
260+ r .clients .cacheMu .Lock ()
261+ c , ok := r .clients .cache [idx ]
262+ r .clients .cacheMu .Unlock ()
263+ if ok {
264+ return c , nil
265+ }
266+ c , err := driver .Boot (ctx , baseCtx , r .nodes [idx ].Driver , pw )
267+ if err != nil {
268+ return nil , err
269+ }
270+ r .clients .cacheMu .Lock ()
271+ r .clients .cache [idx ] = c
272+ r .clients .cacheMu .Unlock ()
273+ return c , nil
245274 })
246275 if err != nil {
247276 return err
@@ -272,14 +301,25 @@ func (r *nodeResolver) opts(ctx context.Context, idxs []int, pw progress.Writer)
272301 continue
273302 }
274303 eg .Go (func () error {
275- opt , err := r .opt .Do (ctx , fmt .Sprint (idx ), func (ctx context.Context ) (gateway.BuildOpts , error ) {
276- opt := gateway.BuildOpts {}
304+ opt , err := r .buildOpts .g .Do (ctx , fmt .Sprint (idx ), func (ctx context.Context ) (gateway.BuildOpts , error ) {
305+ r .buildOpts .cacheMu .Lock ()
306+ opt , ok := r .buildOpts .cache [idx ]
307+ r .buildOpts .cacheMu .Unlock ()
308+ if ok {
309+ return opt , nil
310+ }
277311 _ , err := c .Build (ctx , client.SolveOpt {
278312 Internal : true ,
279313 }, "buildx" , func (ctx context.Context , c gateway.Client ) (* gateway.Result , error ) {
280314 opt = c .BuildOpts ()
281315 return nil , nil
282316 }, nil )
317+ if err != nil {
318+ return gateway.BuildOpts {}, err
319+ }
320+ r .buildOpts .cacheMu .Lock ()
321+ r .buildOpts .cache [idx ] = opt
322+ r .buildOpts .cacheMu .Unlock ()
283323 return opt , err
284324 })
285325 if err != nil {
0 commit comments