Faster and sorted tags

Details about each tag are now fetched by one of NumCPU workers and the
resulting list is sorted by name.
parent 43b903de
Pipeline #40323855 passed with stage
in 41 seconds
......@@ -3,7 +3,10 @@ package cmd
import (
"context"
"fmt"
"runtime"
"sort"
"strings"
"sync"
"github.com/spf13/cobra"
"gitlab.com/zerok/container-inventory/pkg/registryclient"
......@@ -53,26 +56,70 @@ var listTagsCmd = &cobra.Command{
logger.Fatal().Err(err).Msgf("Failed to retrieve tags for %s", repository)
}
mapping := make(map[string][]string)
mlock := sync.RWMutex{}
tagNames := make(chan string, 4)
tagsWithDetails := make(chan tagDetails, 4)
listing := make([]tagDetails, 0, len(tags))
for _, tag := range tags {
t := tagDetails{name: tag}
if withDigest || withDetails {
m, err := c.GetManifest(ctx, repository, tag)
if err != nil {
logger.Fatal().Err(err).Msgf("Failed to retrieve manifest for %s", tag)
}
bs := m.BlobSum()
aliases, ok := mapping[bs]
if !ok {
aliases = make([]string, 0, 2)
numWorkers := runtime.NumCPU()
wg := sync.WaitGroup{}
wg.Add(numWorkers + 1)
workersDone := make(chan struct{}, 1)
go func() {
defer wg.Done()
doneWorkers := 0
for {
select {
case tag := <-tagsWithDetails:
listing = append(listing, tag)
case <-workersDone:
doneWorkers += 1
if doneWorkers == numWorkers {
close(tagsWithDetails)
return
}
}
aliases = append(aliases, tag)
mapping[bs] = aliases
t.digest = m.Digest
t.blobsum = bs
}
listing = append(listing, t)
}()
for i := 0; i < numWorkers; i++ {
go func() {
defer wg.Done()
for tag := range tagNames {
t := tagDetails{name: tag}
if withDigest || withDetails {
logger.Debug().Msgf("Fetching details for %s", tag)
m, err := c.GetManifest(ctx, repository, tag)
if err != nil {
logger.Fatal().Err(err).Msgf("Failed to retrieve manifest for %s", tag)
}
bs := m.BlobSum()
mlock.Lock()
aliases, ok := mapping[bs]
if !ok {
aliases = make([]string, 0, 2)
}
aliases = append(aliases, tag)
mapping[bs] = aliases
mlock.Unlock()
t.digest = m.Digest
t.blobsum = bs
}
tagsWithDetails <- t
}
workersDone <- struct{}{}
}()
}
for _, tag := range tags {
tagNames <- tag
}
close(tagNames)
wg.Wait()
sort.SliceStable(listing, func(i, j int) bool {
return listing[i].name < listing[j].name
})
for _, tag := range listing {
tagName := tag.name
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment