internal/{worker,postgres}: remove alternative modules from search

When processing a module, if it is an alternative module, remove it
from search_documents and imports_unique.

Change-Id: I3fd12e8522331b8a4f060c9576d97c0ee710785d
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/341854
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
diff --git a/internal/postgres/insert_module.go b/internal/postgres/insert_module.go
index e664f60..253fe6e 100644
--- a/internal/postgres/insert_module.go
+++ b/internal/postgres/insert_module.go
@@ -657,17 +657,22 @@
 			log.Debugf(ctx, "ReInsertLatestVersion(%q): no latest-version info", modulePath)
 			return nil
 		}
-		if lmv.GoodVersion == "" {
+		alt, err := isAlternativeModulePath(ctx, tx, modulePath)
+		if err != nil {
+			return err
+		}
+		if alt || lmv.GoodVersion == "" {
 			// A missing GoodVersion means that there are no good versions
-			// remaining, and we should remove the current module from
-			// search_documents.
+			// remaining. In that case, or if this is an alternative module, we
+			// should remove the module from search.
 			if err := deleteModuleOrPackagesInModuleFromSearchDocuments(ctx, tx, modulePath, nil); err != nil {
 				return err
 			}
 			if err := deleteModuleFromImportsUnique(ctx, tx, modulePath); err != nil {
 				return err
 			}
-			log.Debugf(ctx, "ReInsertLatestVersion(%q): no good version; removed from search_documents and imports_unique", modulePath)
+			log.Debugf(ctx, "ReInsertLatestVersion(%q): alternative or no good version; removed from search_documents and imports_unique", modulePath)
+			return nil
 		}
 		// Is the latest good version in search_documents?
 		var x int
@@ -687,19 +692,10 @@
 			return err
 		}
 
-		// The latest good version is not in search_documents. Is this an
-		// alternative module path?
-		alt, err := isAlternativeModulePath(ctx, tx, modulePath)
-		if err != nil {
-			return err
-		}
-		if alt {
-			log.Debugf(ctx, "ReInsertLatestVersion(%q): alternative module path; doing nothing", modulePath)
-			return nil
-		}
+		// The latest good version is not in search_documents, and this is
+		// not an alternative module path. Insert the latest good version.
 
-		// Not an alternative module path. Read the module information at the
-		// latest good version.
+		// Read the module information at the latest good version.
 		pkgMetas, err := getPackagesInUnit(ctx, tx, modulePath, modulePath, lmv.GoodVersion, -1, db.bypassLicenseCheck)
 		if err != nil {
 			return err
diff --git a/internal/postgres/insert_module_test.go b/internal/postgres/insert_module_test.go
index 76a9c6b..66233bf 100644
--- a/internal/postgres/insert_module_test.go
+++ b/internal/postgres/insert_module_test.go
@@ -620,9 +620,7 @@
 	defer release()
 	ctx := context.Background()
 
-	const modulePath = "m.com/a"
-
-	insert := func(version string, status int, imports []string, modfile string) {
+	insert := func(modulePath, version string, status int, imports []string, modfile string) {
 		m := sample.Module(modulePath, version, "pkg")
 		pkg := m.Packages()[0]
 		pkg.Documentation[0].Synopsis = version
@@ -647,15 +645,15 @@
 		}
 	}
 
-	check := func(wantVersion string, wantImports []string) {
+	check := func(modPath, wantVersion string, wantImports []string) {
 		t.Helper()
 		var gotVersion, gotSynopsis string
 		err := testDB.db.QueryRow(ctx, `
 			SELECT version, synopsis
 			FROM search_documents
-			WHERE module_path = 'm.com/a'
-			AND package_path = 'm.com/a/pkg'
-		`).Scan(&gotVersion, &gotSynopsis)
+			WHERE module_path = $1
+			AND package_path = $1 || '/pkg'
+		`, modPath).Scan(&gotVersion, &gotSynopsis)
 		if errors.Is(err, sql.ErrNoRows) {
 			gotVersion = ""
 			gotSynopsis = ""
@@ -669,9 +667,9 @@
 		gotImports, err := testDB.db.CollectStrings(ctx, `
 			SELECT to_path
 			FROM imports_unique
-			WHERE from_path = 'm.com/a/pkg'
-			AND from_module_path = 'm.com/a'
-		`)
+			WHERE from_path = $1 || '/pkg'
+			AND from_module_path = $1
+		`, modPath)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -683,22 +681,33 @@
 	}
 
 	imports1 := []string{"fmt", "log"}
+	const modPath1 = "m.com/a"
 	// Insert a good module. It should be in search_documents and imports_unique.
-	insert("v1.1.0", 200, imports1, "")
-	check("v1.1.0", imports1)
+	insert(modPath1, "v1.1.0", 200, imports1, "")
+	check(modPath1, "v1.1.0", imports1)
 
 	// Insert a higher, good version. It should replace the first.
 	imports2 := []string{"log", "strings"}
-	insert("v1.2.0", 200, imports2, "")
-	check("v1.2.0", imports2)
+	insert(modPath1, "v1.2.0", 200, imports2, "")
+	check(modPath1, "v1.2.0", imports2)
 
 	// Now an even higher, bad version comes along that retracts v1.2.0.
 	// The search_documents and imports_unique tables should go back to v1.1.0.
-	insert("v1.3.0", 400, nil, "retract v1.2.0")
-	check("v1.1.0", imports1)
+	insert(modPath1, "v1.3.0", 400, nil, "retract v1.2.0")
+	check(modPath1, "v1.1.0", imports1)
 
 	// Now a still higher version comes along that retracts everything. The
 	// module should no longer be in search_documents or imports_unique.
-	insert("v1.4.0", 200, nil, "retract [v1.0.0, v1.4.0]")
-	check("", nil)
+	insert(modPath1, "v1.4.0", 200, nil, "retract [v1.0.0, v1.4.0]")
+	check(modPath1, "", nil)
+
+	// Insert another good module.
+	const modPath2 = "m.com/b"
+	insert(modPath2, "v1.1.0", 200, imports1, "")
+	check(modPath2, "v1.1.0", imports1)
+
+	// A later version makes this an alternative module.
+	// The module should be removed from search.
+	insert(modPath2, "v1.2.0", 491, imports1, "")
+	check(modPath2, "", nil)
 }
diff --git a/internal/worker/fetch.go b/internal/worker/fetch.go
index 428e3aa..94a4b44 100644
--- a/internal/worker/fetch.go
+++ b/internal/worker/fetch.go
@@ -118,7 +118,7 @@
 	// Check if the latest good version of the module is not the one in search_documents,
 	// and insert it there and in imports_unique if so.
 	// Do not bother if this is an alternative module path.
-	if ft.Status != derrors.ToStatus(derrors.AlternativeModule) || lmv == nil || lmv.CookedVersion != ft.ResolvedVersion {
+	if lmv == nil || lmv.CookedVersion != ft.ResolvedVersion {
 		if err := f.DB.ReInsertLatestVersion(ctx, modulePath); err != nil {
 			log.Error(ctx, err)
 			if ft.Status != http.StatusInternalServerError {