diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go index 121a19e..89466a7 100644 --- a/cmd/mbf/main.go +++ b/cmd/mbf/main.go @@ -12,6 +12,8 @@ import ( "runtime" "strconv" "strings" + "sync" + "sync/atomic" "syscall" "time" "unique" @@ -265,32 +267,72 @@ func main() { }, ) - c.NewCommand("updates", command.UsageInternal, func([]string) error { - var n int - for i := range rosa.PresetEnd { - p := rosa.PArtifact(i) - meta := rosa.GetMetadata(p) - if meta.ID == 0 { - continue + { + var flagJobs int + c.NewCommand("updates", command.UsageInternal, func([]string) error { + var ( + errsMu sync.Mutex + errs []error + + n atomic.Uint64 + ) + + w := make(chan rosa.PArtifact) + var wg sync.WaitGroup + for range max(flagJobs, 1) { + wg.Go(func() { + for p := range w { + meta := rosa.GetMetadata(p) + if meta.ID == 0 { + continue + } + + v, err := meta.GetVersions(ctx) + if err != nil { + errsMu.Lock() + errs = append(errs, err) + errsMu.Unlock() + continue + } + + if current, latest := + rosa.Std.Version(p), + meta.GetLatest(v); current != latest { + + n.Add(1) + log.Printf("%s %s < %s", meta.Name, current, latest) + continue + } + + msg.Verbosef("%s is up to date", meta.Name) + } + }) } - if v, err := meta.GetVersions(ctx); err != nil { - return err - } else if current, latest := - rosa.Std.Version(p), - meta.GetLatest(v); current != latest { - n++ - log.Printf("%s %s < %s", meta.Name, current, latest) - } else { - msg.Verbosef("%s is up to date", meta.Name) + done: + for i := range rosa.PresetEnd { + select { + case w <- rosa.PArtifact(i): + break + case <-ctx.Done(): + break done + } } - } + close(w) + wg.Wait() - if n > 0 { - return errors.New(strconv.Itoa(n) + " packages are out of date") - } - return nil - }) + if v := n.Load(); v > 0 { + errs = append(errs, errors.New(strconv.Itoa(int(v))+ + " package(s) are out of date")) + } + return errors.Join(errs...) + }). + Flag( + &flagJobs, + "j", command.IntFlag(32), + "Maximum number of simultaneous connections", + ) + } { var ( @@ -565,6 +607,16 @@ func main() { if cache != nil { cache.Close() } - log.Fatal(err) + if w, ok := err.(interface{ Unwrap() []error }); !ok { + log.Fatal(err) + } else { + errs := w.Unwrap() + for i, e := range errs { + if i == len(errs)-1 { + log.Fatal(e) + } + log.Println(e) + } + } }) }