Skip to content

Commit bfc2a45

Browse files
committed
internal/frontend: allow refetch of paths that previously failed
When a fetch request results in a 404, it's possible that the module path will appear later in the index. Similarly, when a fetch request results in a 480 or 500, it's possible that the error was transient or has been fixed but not yet reprocessed. In these cases, we should allow the user to refetch the path after the taskIDChangeInterval has passed. For golang/go#36811 For golang/go#37002 Change-Id: Ia4813140ca793b7b91d80bdc196f61af075766ca Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/244601 Reviewed-by: Jonathan Amsterdam <[email protected]>
1 parent f37c9e1 commit bfc2a45

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

internal/frontend/fetch.go

+26-6
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func (s *Server) checkPossibleModulePaths(ctx context.Context, db *postgres.DB,
187187
// Before enqueuing the module version to be fetched, check if we
188188
// have already attempted to fetch it in the past. If so, just
189189
// return the result from that fetch process.
190-
fr := checkForPath(ctx, db, fullPath, modulePath, requestedVersion)
190+
fr := checkForPath(ctx, db, fullPath, modulePath, requestedVersion, s.taskIDChangeInterval)
191191
if !shouldQueue || fr.status != statusNotFoundInVersionMap {
192192
results[i] = fr
193193
return
@@ -200,7 +200,7 @@ func (s *Server) checkPossibleModulePaths(ctx context.Context, db *postgres.DB,
200200
}
201201
// After the fetch request is enqueued, poll the database until it has been
202202
// inserted or the request times out.
203-
fr = pollForPath(ctx, db, pollEvery, fullPath, modulePath, requestedVersion)
203+
fr = pollForPath(ctx, db, pollEvery, fullPath, modulePath, requestedVersion, s.taskIDChangeInterval)
204204
logf := log.Infof
205205
if fr.status == http.StatusInternalServerError {
206206
logf = log.Errorf
@@ -270,7 +270,7 @@ func displayPath(path, version string) string {
270270

271271
// pollForPath polls the database until a row for fullPath is found.
272272
func pollForPath(ctx context.Context, db *postgres.DB, pollEvery time.Duration,
273-
fullPath, modulePath, requestedVersion string) *fetchResult {
273+
fullPath, modulePath, requestedVersion string, taskIDChangeInterval time.Duration) *fetchResult {
274274
fr := &fetchResult{modulePath: modulePath}
275275
defer derrors.Wrap(&fr.err, "pollForRedirectURL(%q, %q, %q)", modulePath, fullPath, requestedVersion)
276276
ticker := time.NewTicker(pollEvery)
@@ -285,7 +285,7 @@ func pollForPath(ctx context.Context, db *postgres.DB, pollEvery time.Duration,
285285
case <-ticker.C:
286286
ctx2, cancel := context.WithTimeout(ctx, pollEvery)
287287
defer cancel()
288-
fr = checkForPath(ctx2, db, fullPath, modulePath, requestedVersion)
288+
fr = checkForPath(ctx2, db, fullPath, modulePath, requestedVersion, taskIDChangeInterval)
289289
if fr.status != statusNotFoundInVersionMap {
290290
return fr
291291
}
@@ -299,7 +299,8 @@ func pollForPath(ctx context.Context, db *postgres.DB, pollEvery time.Duration,
299299
// process that was initiated is not yet complete. If the row exists version_map
300300
// but not paths, it means that a module was found at the requestedVersion, but
301301
// not the fullPath, so errPathDoesNotExistInModule is returned.
302-
func checkForPath(ctx context.Context, db *postgres.DB, fullPath, modulePath, requestedVersion string) (fr *fetchResult) {
302+
func checkForPath(ctx context.Context, db *postgres.DB,
303+
fullPath, modulePath, requestedVersion string, taskIDChangeInterval time.Duration) (fr *fetchResult) {
303304
defer func() {
304305
// Based on
305306
// https://github.com/lib/pq/issues/577#issuecomment-298341053, it seems
@@ -344,7 +345,26 @@ func checkForPath(ctx context.Context, db *postgres.DB, fullPath, modulePath, re
344345
goModPath: vm.GoModPath,
345346
}
346347
switch fr.status {
347-
case http.StatusNotFound:
348+
case http.StatusNotFound,
349+
derrors.ToStatus(derrors.DBModuleInsertInvalid),
350+
http.StatusInternalServerError:
351+
if time.Since(vm.UpdatedAt) > taskIDChangeInterval {
352+
// If the duration of taskIDChangeInterval has passed since
353+
// a module_path was last inserted into version_map with a failed status,
354+
// treat that data as expired.
355+
//
356+
// It is possible that the module has appeared in the Go Module
357+
// Mirror during that time, the failure was transient, or the
358+
// error has been fixed but the module version has not yet been
359+
// reprocessed.
360+
//
361+
// Return statusNotFoundInVersionMap here, so that the fetch
362+
// request will try to fetch this module version again.
363+
// Since the taskIDChangeInterval has passed, it is now possible to
364+
// enqueue that module version to the frontend task queue again.
365+
fr.status = statusNotFoundInVersionMap
366+
return fr
367+
}
348368
// The version_map indicates that the proxy returned a 404/410.
349369
fr.err = errModuleDoesNotExist
350370
return fr

0 commit comments

Comments
 (0)