in pkg/updater/read.go [420:540]
func readResult(parent context.Context, client gcs.Downloader, build gcs.Build, stop time.Time) (*gcsResult, error) {
ctx, cancel := context.WithCancel(parent) // Allows aborting after first error
defer cancel()
result := gcsResult{
job: build.Job(),
build: build.Build(),
}
ec := make(chan error) // Receives errors from anyone
var lock sync.Mutex
addMalformed := func(s ...string) {
lock.Lock()
defer lock.Unlock()
result.malformed = append(result.malformed, s...)
}
var work int
// Download podinfo.json
work++
go func() {
pi, err := build.PodInfo(ctx, client)
switch {
case errors.Is(err, io.EOF):
addMalformed("podinfo.json")
err = nil
case err != nil:
err = fmt.Errorf("podinfo: %w", err)
case pi != nil:
result.podInfo = *pi
}
select {
case <-ctx.Done():
case ec <- err:
}
}()
// Download started.json
work++
go func() {
s, err := build.Started(ctx, client)
switch {
case errors.Is(err, io.EOF):
addMalformed("started.json")
err = nil
case err != nil:
err = fmt.Errorf("started: %w", err)
case time.Unix(s.Timestamp, 0).Before(stop):
err = &ancientError{fmt.Sprintf("build too old; started %v before %v)", s.Timestamp, stop.Unix())}
if s.Timestamp == 0 {
err = &noStartError{}
}
default:
result.started = *s
}
select {
case <-ctx.Done():
case ec <- err:
}
}()
// Download finished.json
work++
go func() {
f, err := build.Finished(ctx, client)
switch {
case errors.Is(err, io.EOF):
addMalformed("finished.json")
err = nil
case err != nil:
err = fmt.Errorf("finished: %w", err)
default:
result.finished = *f
}
select {
case <-ctx.Done():
case ec <- err:
}
}()
// Download suites
work++
go func() {
suites, err := readSuites(ctx, client, build)
if err != nil {
err = fmt.Errorf("suites: %w", err)
}
var problems []string
for _, s := range suites {
if s.Err != nil {
p := strings.TrimPrefix(s.Path, build.Path.String())
problems = append(problems, fmt.Sprintf("%s: %s", p, s.Err))
} else {
result.suites = append(result.suites, s)
}
}
if len(problems) > 0 {
addMalformed(problems...)
}
select {
case <-ctx.Done():
case ec <- err:
}
}()
for ; work > 0; work-- {
select {
case <-ctx.Done():
return nil, fmt.Errorf("timeout: %w", ctx.Err())
case err := <-ec:
if err != nil {
return nil, err
}
}
}
sort.Slice(result.malformed, func(i, j int) bool {
return result.malformed[i] < result.malformed[j]
})
return &result, nil
}