aboutsummaryrefslogtreecommitdiff
path: root/internal/postgres/insert_module.go
diff options
context:
space:
mode:
authorJonathan Amsterdam <jba@google.com>2021-03-12 15:18:32 -0500
committerJonathan Amsterdam <jba@google.com>2021-03-16 18:33:03 +0000
commit38233971b438ea5c22111c50740f996e34f89dfb (patch)
tree13bc9f1ab17f5448e7efaba0305b817ca5332b75 /internal/postgres/insert_module.go
parent5a3c43e7e8b7a084d4a72d369c8f71e7c1a9e61d (diff)
downloadgo-x-pkgsite-38233971b438ea5c22111c50740f996e34f89dfb.tar.xz
internal/worker,etc.: improvements to latest-version info
- Fetch and update the latest-version info before processing a module rather than after, so the information in the DB matches what InsertModule is using. - Pass latest-version info to InsertModule so it can use it to decide whether the version being inserted is the latest version. - InsertModule writes the good latest version to the latest_module_versions table while holding the advisory lock, avoiding a race condition where two different versions both think they're the latest. For golang/go#44710 Change-Id: Id5e8fa7a384ec6d4d86257362fd33a8fcd5215f7 Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/301929 Trust: Jonathan Amsterdam <jba@google.com> Run-TryBot: Jonathan Amsterdam <jba@google.com> TryBot-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: Julie Qiu <julie@golang.org>
Diffstat (limited to 'internal/postgres/insert_module.go')
-rw-r--r--internal/postgres/insert_module.go47
1 files changed, 16 insertions, 31 deletions
diff --git a/internal/postgres/insert_module.go b/internal/postgres/insert_module.go
index ce4e91e8..3f6cf825 100644
--- a/internal/postgres/insert_module.go
+++ b/internal/postgres/insert_module.go
@@ -16,7 +16,6 @@ import (
"strings"
"unicode/utf8"
- "github.com/Masterminds/squirrel"
"github.com/lib/pq"
"go.opencensus.io/trace"
"golang.org/x/mod/module"
@@ -30,11 +29,10 @@ import (
"golang.org/x/pkgsite/internal/version"
)
-// InsertModule inserts a version into the database using
-// db.saveVersion, along with a search document corresponding to each of its
-// packages.
+// InsertModule inserts a version into the database using db.saveVersion, along
+// with a search document corresponding to each of its packages.
// It returns whether the version inserted was the latest for the given module path.
-func (db *DB) InsertModule(ctx context.Context, m *internal.Module) (isLatest bool, err error) {
+func (db *DB) InsertModule(ctx context.Context, m *internal.Module, lmv *internal.LatestModuleVersions) (isLatest bool, err error) {
defer func() {
if m == nil {
derrors.WrapStack(&err, "DB.InsertModule(ctx, nil)")
@@ -61,7 +59,7 @@ func (db *DB) InsertModule(ctx context.Context, m *internal.Module) (isLatest bo
// If we are not bypassing license checking, remove data for non-redistributable modules.
m.RemoveNonRedistributableData()
}
- return db.saveModule(ctx, m)
+ return db.saveModule(ctx, m, lmv)
}
// saveModule inserts a Module into the database along with its packages,
@@ -74,7 +72,7 @@ func (db *DB) InsertModule(ctx context.Context, m *internal.Module) (isLatest bo
//
// A derrors.InvalidArgument error will be returned if the given module and
// licenses are invalid.
-func (db *DB) saveModule(ctx context.Context, m *internal.Module) (isLatest bool, err error) {
+func (db *DB) saveModule(ctx context.Context, m *internal.Module, lmv *internal.LatestModuleVersions) (isLatest bool, err error) {
defer derrors.WrapStack(&err, "saveModule(ctx, tx, Module(%q, %q))", m.ModulePath, m.Version)
ctx, span := trace.StartSpan(ctx, "saveModule")
defer span.End()
@@ -124,13 +122,23 @@ func (db *DB) saveModule(ctx context.Context, m *internal.Module) (isLatest bool
// We only insert into imports_unique and search_documents if this is
// the latest version of the module.
- isLatest, err = isLatestVersion(ctx, tx, m.ModulePath, m.Version)
+ // By the time this function is called, we've already inserted into the modules table.
+ // So the query in getLatestGoodVersion will include this version.
+ latest, err := getLatestGoodVersion(ctx, tx, m.ModulePath, lmv)
if err != nil {
return err
}
+ // Update the DB with the latest version, even if we are not the latest.
+ // (Perhaps we just learned of a retraction that affects the good latest
+ // version.)
+ if err := updateLatestGoodVersion(ctx, tx, m.ModulePath, latest); err != nil {
+ return err
+ }
+ isLatest = m.Version == latest
if !isLatest {
return nil
}
+ // Here, this module is the latest good version.
if err := insertImportsUnique(ctx, tx, m); err != nil {
return err
@@ -611,29 +619,6 @@ func lock(ctx context.Context, tx *database.DB, modulePath string) (err error) {
return nil
}
-// isLatestVersion reports whether version is the latest version of the module.
-func isLatestVersion(ctx context.Context, ddb *database.DB, modulePath, resolvedVersion string) (_ bool, err error) {
- defer derrors.WrapStack(&err, "isLatestVersion(ctx, tx, %q)", modulePath)
-
- q, args, err := orderByLatest(squirrel.Select("m.version").
- From("modules m").
- Where(squirrel.Eq{"m.module_path": modulePath})).
- Limit(1).
- ToSql()
- if err != nil {
- return false, err
- }
- row := ddb.QueryRow(ctx, q, args...)
- var v string
- if err := row.Scan(&v); err != nil {
- if err == sql.ErrNoRows {
- return true, nil // It's the only version, so it's also the latest.
- }
- return false, err
- }
- return resolvedVersion == v, nil
-}
-
// validateModule checks that fields needed to insert a module into the database
// are present. Otherwise, it returns an error listing the reasons the module
// cannot be inserted. Since the problems it looks for are most likely on our