in internal/worker/fetch.go [288:392]
func (f *Fetcher) fetchAndInsertModule(ctx context.Context, modulePath, requestedVersion string, lmv *internal.LatestModuleVersions) *fetchTask {
ft := &fetchTask{
FetchResult: fetch.FetchResult{
ModulePath: modulePath,
RequestedVersion: requestedVersion,
},
timings: map[string]time.Duration{},
}
defer func() {
derrors.Wrap(&ft.Error, "fetchAndInsertModule(%q, %q)", modulePath, requestedVersion)
if ft.Error != nil {
ft.Status = derrors.ToStatus(ft.Error)
ft.ResolvedVersion = requestedVersion
}
}()
exc, err := f.DB.IsExcluded(ctx, modulePath)
if err != nil {
ft.Error = err
return ft
}
if exc {
ft.Error = derrors.Excluded
return ft
}
proxyGetter := fetch.NewProxyModuleGetter(f.ProxyClient, f.SourceClient)
// Fetch the module, and the current @main and @master version of this module.
// The @main and @master version will be used to update the version_map
// target if applicable.
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
start := time.Now()
fr := fetch.FetchModule(ctx, modulePath, requestedVersion, proxyGetter)
if fr == nil {
panic("fetch.FetchModule should never return a nil FetchResult")
}
ft.FetchResult = *fr
ft.timings["fetch.FetchModule"] = time.Since(start)
}()
// Do not resolve the @main and @master version if proxy fetch is disabled.
var main string
wg.Add(1)
go func() {
defer wg.Done()
if !f.ProxyClient.FetchDisabled() {
main = resolvedVersion(ctx, modulePath, internal.MainVersion, proxyGetter)
}
}()
var master string
wg.Add(1)
go func() {
defer wg.Done()
if !f.ProxyClient.FetchDisabled() {
master = resolvedVersion(ctx, modulePath, internal.MasterVersion, proxyGetter)
}
}()
wg.Wait()
ft.MainVersion = main
ft.MasterVersion = master
// There was an error fetching this module.
if ft.Error != nil {
logf := log.Infof
if ft.Status >= 500 && ft.Status != derrors.ToStatus(derrors.ProxyTimedOut) {
logf = log.Warningf
}
logf(ctx, "Error executing fetch: %v (code %d)", ft.Error, ft.Status)
return ft
}
// The module was successfully fetched.
log.Debugf(ctx, "fetch.FetchModule succeeded for %s@%s", ft.ModulePath, ft.RequestedVersion)
// Determine the current latest-version information for this module.
start := time.Now()
isLatest, err := f.DB.InsertModule(ctx, ft.Module, lmv)
ft.timings["db.InsertModule"] = time.Since(start)
if err != nil {
ft.Status = derrors.ToStatus(err)
ft.Error = err
if ft.Status >= 500 {
log.Error(ctx, err)
} else {
log.Info(ctx, err)
}
return ft
}
log.Debugf(ctx, "db.InsertModule succeeded for %s@%s", ft.ModulePath, ft.RequestedVersion)
// Invalidate the cache if we just processed the latest version of a module.
if isLatest {
if err := f.invalidateCache(ctx, ft.ModulePath); err != nil {
// Failure to invalidate the cache is not that serious; at worst it means some pages will be stale.
// (Cache TTLs for details pages configured in internal/frontend/server.go must not be too long,
// to account for this possibility.)
log.Errorf(ctx, "failed to invalidate cache for %s: %v", ft.ModulePath, err)
} else {
log.Debugf(ctx, "invalidated cache for %s", ft.ModulePath)
}
}
return ft
}