mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-08-20 09:21:11 +00:00
fix: upgrade fails or hang at migration[32]: Migrate maven package name concatenation (#8609)
- Some SQL queries were not being run in the transaction of v32, which could lead to the migration failing or hanging indefinitely. - Use `db.WithTx` to get a `context.Context` that will make sure to run SQL queries in the transaction. - Using `db.DefaultContext` is fine to be used as parent context for starting the transaction, in all cases of starting the migration `x` and `db.DefaultContext` will point to the same engine. - Resolves forgejo/forgejo#8580 ## Testing 1. Have a v11 Forgejo database with a maven package. 2. Run this migration. <!--start release-notes-assistant--> ## Release notes <!--URL:https://codeberg.org/forgejo/forgejo--> - Bug fixes - [PR](https://codeberg.org/forgejo/forgejo/pulls/8609): <!--number 8609 --><!--line 0 --><!--description dXBncmFkZSBmYWlscyBvciBoYW5nIGF0IG1pZ3JhdGlvblszMl06IE1pZ3JhdGUgbWF2ZW4gcGFja2FnZSBuYW1lIGNvbmNhdGVuYXRpb24=-->upgrade fails or hang at migration[32]: Migrate maven package name concatenation<!--description--> <!--end release-notes-assistant--> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8609 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Reviewed-by: JSchlarb <jschlarb@noreply.codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
parent
34caa374d6
commit
cf46b22272
1 changed files with 40 additions and 47 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"forgejo.org/models/db"
|
||||||
"forgejo.org/models/packages"
|
"forgejo.org/models/packages"
|
||||||
"forgejo.org/modules/json"
|
"forgejo.org/modules/json"
|
||||||
"forgejo.org/modules/log"
|
"forgejo.org/modules/log"
|
||||||
|
@ -52,55 +53,50 @@ type mavenPackageResult struct {
|
||||||
// ChangeMavenArtifactConcatenation resolves old dash-concatenated Maven coordinates and regenerates metadata.
|
// ChangeMavenArtifactConcatenation resolves old dash-concatenated Maven coordinates and regenerates metadata.
|
||||||
// Note: runs per-owner in a single transaction; failures roll back all owners.
|
// Note: runs per-owner in a single transaction; failures roll back all owners.
|
||||||
func ChangeMavenArtifactConcatenation(x *xorm.Engine) error {
|
func ChangeMavenArtifactConcatenation(x *xorm.Engine) error {
|
||||||
sess := x.NewSession()
|
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
defer sess.Close()
|
// get unique owner IDs of Maven packages
|
||||||
|
var ownerIDs []*int64
|
||||||
if err := sess.Begin(); err != nil {
|
if err := db.GetEngine(ctx).
|
||||||
return err
|
Table("package").
|
||||||
}
|
Select("package.owner_id").
|
||||||
|
Where("package.type = 'maven'").
|
||||||
// get unique owner IDs of Maven packages
|
GroupBy("package.owner_id").
|
||||||
var ownerIDs []*int64
|
OrderBy("package.owner_id DESC").
|
||||||
if err := sess.
|
Find(&ownerIDs); err != nil {
|
||||||
Table("package").
|
return err
|
||||||
Select("package.owner_id").
|
|
||||||
Where("package.type = 'maven'").
|
|
||||||
GroupBy("package.owner_id").
|
|
||||||
OrderBy("package.owner_id DESC").
|
|
||||||
Find(&ownerIDs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, id := range ownerIDs {
|
|
||||||
if err := fixMavenArtifactPerOwner(sess, id); err != nil {
|
|
||||||
log.Error("owner %d migration failed: %v", id, err)
|
|
||||||
return err // rollback all
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return sess.Commit()
|
for _, id := range ownerIDs {
|
||||||
|
if err := fixMavenArtifactPerOwner(ctx, id); err != nil {
|
||||||
|
log.Error("owner %d migration failed: %v", id, err)
|
||||||
|
return err // rollback all
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixMavenArtifactPerOwner(sess *xorm.Session, ownerID *int64) error {
|
func fixMavenArtifactPerOwner(ctx context.Context, ownerID *int64) error {
|
||||||
results, err := getMavenPackageResultsToUpdate(sess, ownerID)
|
results, err := getMavenPackageResultsToUpdate(ctx, ownerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = resolvePackageCollisions(results, sess); err != nil {
|
if err = resolvePackageCollisions(ctx, results); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = processPackageVersions(results, sess); err != nil {
|
if err = processPackageVersions(ctx, results); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return processPackageFiles(results, sess)
|
return processPackageFiles(ctx, results)
|
||||||
}
|
}
|
||||||
|
|
||||||
// processPackageFiles updates Maven package files and versions in the database
|
// processPackageFiles updates Maven package files and versions in the database
|
||||||
// Returns an error if any database or processing operation fails.
|
// Returns an error if any database or processing operation fails.
|
||||||
func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) error {
|
func processPackageFiles(ctx context.Context, results []*mavenPackageResult) error {
|
||||||
processedVersion := make(map[string][]*mavenPackageResult)
|
processedVersion := make(map[string][]*mavenPackageResult)
|
||||||
|
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
|
@ -113,7 +109,7 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
|
||||||
if r.PackageVersion.ID != r.PackageFile.VersionID {
|
if r.PackageVersion.ID != r.PackageFile.VersionID {
|
||||||
pattern := strings.TrimSuffix(r.PackageFile.Name, ".pom") + "%"
|
pattern := strings.TrimSuffix(r.PackageFile.Name, ".pom") + "%"
|
||||||
// Per routers/api/packages/maven/maven.go:338, POM files already have the `IsLead`, so no update needed for this prop
|
// Per routers/api/packages/maven/maven.go:338, POM files already have the `IsLead`, so no update needed for this prop
|
||||||
if _, err := sess.Exec("UPDATE package_file SET version_id = ? WHERE version_id = ? and name like ?", r.PackageVersion.ID, r.PackageFile.VersionID, pattern); err != nil {
|
if _, err := db.GetEngine(ctx).Exec("UPDATE package_file SET version_id = ? WHERE version_id = ? and name like ?", r.PackageVersion.ID, r.PackageFile.VersionID, pattern); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,14 +124,14 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
|
||||||
|
|
||||||
rs := packageResults[0]
|
rs := packageResults[0]
|
||||||
|
|
||||||
pf, md, err := parseMetadata(sess, rs)
|
pf, md, err := parseMetadata(ctx, rs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pf != nil && md != nil && md.GroupID == rs.GroupID && md.ArtifactID == rs.ArtifactID {
|
if pf != nil && md != nil && md.GroupID == rs.GroupID && md.ArtifactID == rs.ArtifactID {
|
||||||
if pf.VersionID != rs.PackageFile.VersionID {
|
if pf.VersionID != rs.PackageFile.VersionID {
|
||||||
if _, err := sess.ID(pf.ID).Cols("version_id").Update(pf); err != nil {
|
if _, err := db.GetEngine(ctx).ID(pf.ID).Cols("version_id").Update(pf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,11 +146,9 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
|
||||||
|
|
||||||
// parseMetadata retrieves metadata for a Maven package file from the database and decodes it into a Metadata object.
|
// parseMetadata retrieves metadata for a Maven package file from the database and decodes it into a Metadata object.
|
||||||
// Returns the associated PackageFile, Metadata, and any error encountered during processing.
|
// Returns the associated PackageFile, Metadata, and any error encountered during processing.
|
||||||
func parseMetadata(sess *xorm.Session, snapshot *mavenPackageResult) (*packages.PackageFile, *Metadata, error) {
|
func parseMetadata(ctx context.Context, snapshot *mavenPackageResult) (*packages.PackageFile, *Metadata, error) {
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
var pf packages.PackageFile
|
var pf packages.PackageFile
|
||||||
found, err := sess.Table(pf).
|
found, err := db.GetEngine(ctx).Table(pf).
|
||||||
Where("version_id = ?", snapshot.PackageFile.VersionID). // still the old id
|
Where("version_id = ?", snapshot.PackageFile.VersionID). // still the old id
|
||||||
And("lower_name = ?", "maven-metadata.xml").
|
And("lower_name = ?", "maven-metadata.xml").
|
||||||
Get(&pf)
|
Get(&pf)
|
||||||
|
@ -183,7 +177,7 @@ func parseMetadata(sess *xorm.Session, snapshot *mavenPackageResult) (*packages.
|
||||||
|
|
||||||
// processPackageVersions processes Maven package versions by updating metadata or inserting new records as necessary.
|
// processPackageVersions processes Maven package versions by updating metadata or inserting new records as necessary.
|
||||||
// It avoids redundant updates by tracking already processed versions using a map. Returns an error on failure.
|
// It avoids redundant updates by tracking already processed versions using a map. Returns an error on failure.
|
||||||
func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) error {
|
func processPackageVersions(ctx context.Context, results []*mavenPackageResult) error {
|
||||||
processedVersion := make(map[string]int64)
|
processedVersion := make(map[string]int64)
|
||||||
|
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
|
@ -196,14 +190,14 @@ func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) e
|
||||||
|
|
||||||
// for non collisions, just update the metadata
|
// for non collisions, just update the metadata
|
||||||
if r.PackageVersion.PackageID == r.Package.ID {
|
if r.PackageVersion.PackageID == r.Package.ID {
|
||||||
if _, err := sess.ID(r.PackageVersion.ID).Cols("metadata_json").Update(r.PackageVersion); err != nil {
|
if _, err := db.GetEngine(ctx).ID(r.PackageVersion.ID).Cols("metadata_json").Update(r.PackageVersion); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Info("Create new maven package version for %s:%s", r.PackageName, r.PackageVersion.Version)
|
log.Info("Create new maven package version for %s:%s", r.PackageName, r.PackageVersion.Version)
|
||||||
r.PackageVersion.ID = 0
|
r.PackageVersion.ID = 0
|
||||||
r.PackageVersion.PackageID = r.Package.ID
|
r.PackageVersion.PackageID = r.Package.ID
|
||||||
if _, err := sess.Insert(r.PackageVersion); err != nil {
|
if _, err := db.GetEngine(ctx).Insert(r.PackageVersion); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,10 +210,9 @@ func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) e
|
||||||
|
|
||||||
// getMavenPackageResultsToUpdate retrieves Maven package results that need updates based on the owner ID.
|
// getMavenPackageResultsToUpdate retrieves Maven package results that need updates based on the owner ID.
|
||||||
// It processes POM metadata, fixes package inconsistencies, and filters corrupted package versions.
|
// It processes POM metadata, fixes package inconsistencies, and filters corrupted package versions.
|
||||||
func getMavenPackageResultsToUpdate(sess *xorm.Session, ownerID *int64) ([]*mavenPackageResult, error) {
|
func getMavenPackageResultsToUpdate(ctx context.Context, ownerID *int64) ([]*mavenPackageResult, error) {
|
||||||
ctx := context.Background()
|
|
||||||
var candidates []*mavenPackageResult
|
var candidates []*mavenPackageResult
|
||||||
if err := sess.
|
if err := db.GetEngine(ctx).
|
||||||
Table("package_file").
|
Table("package_file").
|
||||||
Select("package_file.*, package_version.*, package.*").
|
Select("package_file.*, package_version.*, package.*").
|
||||||
Join("INNER", "package_version", "package_version.id = package_file.version_id").
|
Join("INNER", "package_version", "package_version.id = package_file.version_id").
|
||||||
|
@ -265,7 +258,7 @@ func getMavenPackageResultsToUpdate(sess *xorm.Session, ownerID *int64) ([]*mave
|
||||||
|
|
||||||
// resolvePackageCollisions handles name collisions by keeping the first existing record and inserting new Package records for subsequent collisions.
|
// resolvePackageCollisions handles name collisions by keeping the first existing record and inserting new Package records for subsequent collisions.
|
||||||
// Returns a map from PackageName to its resolved Package.ID.
|
// Returns a map from PackageName to its resolved Package.ID.
|
||||||
func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session) error {
|
func resolvePackageCollisions(ctx context.Context, results []*mavenPackageResult) error {
|
||||||
// Group new names by lowerName
|
// Group new names by lowerName
|
||||||
collisions := make(map[string][]string)
|
collisions := make(map[string][]string)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
|
@ -292,7 +285,7 @@ func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session)
|
||||||
} else if list[0] == r.PackageName {
|
} else if list[0] == r.PackageName {
|
||||||
pkgIDByName[r.PackageName] = r.Package.ID
|
pkgIDByName[r.PackageName] = r.Package.ID
|
||||||
|
|
||||||
if _, err = sess.ID(r.Package.ID).Cols("name", "lower_name").Update(r.Package); err != nil {
|
if _, err = db.GetEngine(ctx).ID(r.Package.ID).Cols("name", "lower_name").Update(r.Package); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// create a new entry
|
// create a new entry
|
||||||
|
@ -300,7 +293,7 @@ func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session)
|
||||||
log.Info("Create new maven package for %s", r.Package.Name)
|
log.Info("Create new maven package for %s", r.Package.Name)
|
||||||
|
|
||||||
r.Package.ID = 0
|
r.Package.ID = 0
|
||||||
if _, err = sess.Insert(r.Package); err != nil {
|
if _, err = db.GetEngine(ctx).Insert(r.Package); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue