@@ -8,14 +8,14 @@ import (
8
8
"os/exec"
9
9
"path/filepath"
10
10
"strings"
11
- "sync"
12
11
"time"
13
12
14
13
"github.com/creack/pty"
15
14
"github.com/gookit/color"
16
15
"github.com/segmentio/textio"
17
16
log "github.com/sirupsen/logrus"
18
17
"github.com/spf13/cobra"
18
+ "golang.org/x/sync/errgroup"
19
19
20
20
"github.com/gitpod-io/leeway/pkg/leeway"
21
21
)
@@ -60,6 +60,7 @@ Example use:
60
60
parallel , _ = cmd .Flags ().GetBool ("parallel" )
61
61
rawOutput , _ = cmd .Flags ().GetBool ("raw-output" )
62
62
cacheKey , _ = cmd .Flags ().GetString ("cache-key" )
63
+ maxConcurrentTasks , _ = cmd .Flags ().GetUint ("max-concurrent-tasks" )
63
64
)
64
65
65
66
ws , err := getWorkspace ()
@@ -162,8 +163,18 @@ Example use:
162
163
}
163
164
}
164
165
166
+ var parallelism int
167
+ if parallel {
168
+ parallelism = int (maxConcurrentTasks )
169
+ } else {
170
+ parallelism = - 1
171
+ if maxConcurrentTasks > 0 {
172
+ log .Warn ("max-concurrent-tasks is ignored when not running in parallel" )
173
+ }
174
+ }
175
+
165
176
if watch {
166
- err := executeCommandInLocations (args , locs , noExecCache {}, parallel , rawOutput )
177
+ err := executeCommandInLocations (args , locs , noExecCache {}, parallelism , rawOutput )
167
178
if err != nil {
168
179
log .Error (err )
169
180
}
@@ -172,7 +183,7 @@ Example use:
172
183
for {
173
184
select {
174
185
case <- evt :
175
- err := executeCommandInLocations (args , locs , noExecCache {}, parallel , rawOutput )
186
+ err := executeCommandInLocations (args , locs , noExecCache {}, parallelism , rawOutput )
176
187
if err != nil {
177
188
log .Error (err )
178
189
}
@@ -194,7 +205,7 @@ Example use:
194
205
cache = filesystemExecCache (loc )
195
206
}
196
207
197
- err = executeCommandInLocations (args , locs , cache , parallel , rawOutput )
208
+ err = executeCommandInLocations (args , locs , cache , parallelism , rawOutput )
198
209
if err != nil {
199
210
log .WithError (err ).Fatal ("cannot execut command" )
200
211
}
@@ -208,8 +219,12 @@ type commandExecLocation struct {
208
219
Name string
209
220
}
210
221
211
- func executeCommandInLocations (rawExecCmd []string , locs []commandExecLocation , cache execCache , parallel , rawOutput bool ) error {
212
- var wg sync.WaitGroup
222
+ func executeCommandInLocations (rawExecCmd []string , locs []commandExecLocation , cache execCache , parallelism int , rawOutput bool ) error {
223
+ var eg errgroup.Group
224
+ if parallelism > 0 {
225
+ eg .SetLimit (parallelism )
226
+ }
227
+
213
228
for _ , loc := range locs {
214
229
if ok , _ := cache .NeedsExecution (context .Background (), loc .Package ); ! ok {
215
230
continue
@@ -247,11 +262,9 @@ func executeCommandInLocations(rawExecCmd []string, locs []commandExecLocation,
247
262
go io .Copy (textio .NewPrefixWriter (os .Stdout , prefix ), ptmx )
248
263
//nolint:errcheck
249
264
go io .Copy (ptmx , os .Stdin )
250
- if parallel {
251
- wg .Add (1 )
252
- go func (loc commandExecLocation ) {
253
- defer wg .Done ()
254
-
265
+ if parallelism > - 1 {
266
+ loc := loc
267
+ eg .Go (func () error {
255
268
err := cmd .Wait ()
256
269
if err == nil {
257
270
err = cache .MarkExecuted (context .Background (), loc .Package )
@@ -261,7 +274,8 @@ func executeCommandInLocations(rawExecCmd []string, locs []commandExecLocation,
261
274
} else {
262
275
log .Errorf ("execution failed in %s (%s): %v" , loc .Name , loc .Dir , err )
263
276
}
264
- }(loc )
277
+ return nil
278
+ })
265
279
} else {
266
280
err = cmd .Wait ()
267
281
if err == nil {
@@ -274,8 +288,8 @@ func executeCommandInLocations(rawExecCmd []string, locs []commandExecLocation,
274
288
}
275
289
}
276
290
}
277
- if parallel {
278
- wg .Wait ()
291
+ if parallelism > - 1 {
292
+ _ = eg .Wait ()
279
293
}
280
294
281
295
return nil
@@ -295,6 +309,7 @@ func init() {
295
309
execCmd .Flags ().Bool ("parallel" , false , "Start all executions in parallel independent of their order" )
296
310
execCmd .Flags ().Bool ("raw-output" , false , "Produce output without package prefix" )
297
311
execCmd .Flags ().String ("cache-key" , "" , "Specify a cache key to provide package-cache like execution behaviour" )
312
+ execCmd .Flags ().UintP ("max-concurrent-tasks" , "j" , 0 , "Maximum number of concurrent tasks - 0 means unlimited" )
298
313
execCmd .Flags ().SetInterspersed (true )
299
314
}
300
315
0 commit comments