blob: 2052e422c469b946795dc1720388e335720261fe [file] [log] [blame]
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package worker
import (
"sort"
"sync"
"time"
)
// FetchInfo describes a fetch in progress, or completed.
// It is used to display information on the worker home page.
type FetchInfo struct {
ModulePath string
Version string
ZipSize uint64
Start time.Time
Finish time.Time
Status int
Error error
}
var (
fetchInfoMu sync.Mutex
fetchInfoMap = map[*FetchInfo]struct{}{}
)
func init() {
// Start a goroutine to remove FetchInfos that have been finished for a
// while.
const linger = time.Minute
go func() {
for {
now := time.Now()
fetchInfoMu.Lock()
for fi := range fetchInfoMap {
if !fi.Finish.IsZero() && now.Sub(fi.Finish) > linger {
delete(fetchInfoMap, fi)
}
}
fetchInfoMu.Unlock()
time.Sleep(linger)
}
}()
}
func startFetchInfo(fi *FetchInfo) {
fetchInfoMu.Lock()
defer fetchInfoMu.Unlock()
fetchInfoMap[fi] = struct{}{}
}
func finishFetchInfo(fi *FetchInfo, status int, err error) {
fetchInfoMu.Lock()
defer fetchInfoMu.Unlock()
fi.Finish = time.Now()
fi.Status = status
fi.Error = err
}
// FetchInfos returns information about all fetches in progress,
// sorted by start time.
func FetchInfos() []*FetchInfo {
var fis []*FetchInfo
fetchInfoMu.Lock()
for fi := range fetchInfoMap {
// Copy to avoid races on Status and Error when read by
// worker home page.
cfi := *fi
fis = append(fis, &cfi)
}
fetchInfoMu.Unlock()
// Order first by done-ness, then by age.
sort.Slice(fis, func(i, j int) bool {
if (fis[i].Status == 0) == (fis[j].Status == 0) {
return fis[i].Start.Before(fis[j].Start)
}
return fis[i].Status == 0
})
return fis
}