Skip to content

Commit cf46b22

Browse files
GustedEarl Warren
authored andcommitted
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 <[email protected]> Reviewed-by: JSchlarb <[email protected]> Co-authored-by: Gusted <[email protected]> Co-committed-by: Gusted <[email protected]>
1 parent 34caa37 commit cf46b22

File tree

1 file changed

+39
-46
lines changed
  • models/forgejo_migrations

1 file changed

+39
-46
lines changed

models/forgejo_migrations/v32.go

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strconv"
1313
"strings"
1414

15+
"forgejo.org/models/db"
1516
"forgejo.org/models/packages"
1617
"forgejo.org/modules/json"
1718
"forgejo.org/modules/log"
@@ -52,55 +53,50 @@ type mavenPackageResult struct {
5253
// ChangeMavenArtifactConcatenation resolves old dash-concatenated Maven coordinates and regenerates metadata.
5354
// Note: runs per-owner in a single transaction; failures roll back all owners.
5455
func ChangeMavenArtifactConcatenation(x *xorm.Engine) error {
55-
sess := x.NewSession()
56-
defer sess.Close()
57-
58-
if err := sess.Begin(); err != nil {
59-
return err
60-
}
61-
62-
// get unique owner IDs of Maven packages
63-
var ownerIDs []*int64
64-
if err := sess.
65-
Table("package").
66-
Select("package.owner_id").
67-
Where("package.type = 'maven'").
68-
GroupBy("package.owner_id").
69-
OrderBy("package.owner_id DESC").
70-
Find(&ownerIDs); err != nil {
71-
return err
72-
}
56+
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
57+
// get unique owner IDs of Maven packages
58+
var ownerIDs []*int64
59+
if err := db.GetEngine(ctx).
60+
Table("package").
61+
Select("package.owner_id").
62+
Where("package.type = 'maven'").
63+
GroupBy("package.owner_id").
64+
OrderBy("package.owner_id DESC").
65+
Find(&ownerIDs); err != nil {
66+
return err
67+
}
7368

74-
for _, id := range ownerIDs {
75-
if err := fixMavenArtifactPerOwner(sess, id); err != nil {
76-
log.Error("owner %d migration failed: %v", id, err)
77-
return err // rollback all
69+
for _, id := range ownerIDs {
70+
if err := fixMavenArtifactPerOwner(ctx, id); err != nil {
71+
log.Error("owner %d migration failed: %v", id, err)
72+
return err // rollback all
73+
}
7874
}
79-
}
8075

81-
return sess.Commit()
76+
return nil
77+
})
8278
}
8379

84-
func fixMavenArtifactPerOwner(sess *xorm.Session, ownerID *int64) error {
85-
results, err := getMavenPackageResultsToUpdate(sess, ownerID)
80+
func fixMavenArtifactPerOwner(ctx context.Context, ownerID *int64) error {
81+
results, err := getMavenPackageResultsToUpdate(ctx, ownerID)
8682
if err != nil {
8783
return err
8884
}
8985

90-
if err = resolvePackageCollisions(results, sess); err != nil {
86+
if err = resolvePackageCollisions(ctx, results); err != nil {
9187
return err
9288
}
9389

94-
if err = processPackageVersions(results, sess); err != nil {
90+
if err = processPackageVersions(ctx, results); err != nil {
9591
return err
9692
}
9793

98-
return processPackageFiles(results, sess)
94+
return processPackageFiles(ctx, results)
9995
}
10096

10197
// processPackageFiles updates Maven package files and versions in the database
10298
// Returns an error if any database or processing operation fails.
103-
func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) error {
99+
func processPackageFiles(ctx context.Context, results []*mavenPackageResult) error {
104100
processedVersion := make(map[string][]*mavenPackageResult)
105101

106102
for _, r := range results {
@@ -113,7 +109,7 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
113109
if r.PackageVersion.ID != r.PackageFile.VersionID {
114110
pattern := strings.TrimSuffix(r.PackageFile.Name, ".pom") + "%"
115111
// Per routers/api/packages/maven/maven.go:338, POM files already have the `IsLead`, so no update needed for this prop
116-
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 {
112+
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 {
117113
return err
118114
}
119115
}
@@ -128,14 +124,14 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
128124

129125
rs := packageResults[0]
130126

131-
pf, md, err := parseMetadata(sess, rs)
127+
pf, md, err := parseMetadata(ctx, rs)
132128
if err != nil {
133129
return err
134130
}
135131

136132
if pf != nil && md != nil && md.GroupID == rs.GroupID && md.ArtifactID == rs.ArtifactID {
137133
if pf.VersionID != rs.PackageFile.VersionID {
138-
if _, err := sess.ID(pf.ID).Cols("version_id").Update(pf); err != nil {
134+
if _, err := db.GetEngine(ctx).ID(pf.ID).Cols("version_id").Update(pf); err != nil {
139135
return err
140136
}
141137
}
@@ -150,11 +146,9 @@ func processPackageFiles(results []*mavenPackageResult, sess *xorm.Session) erro
150146

151147
// parseMetadata retrieves metadata for a Maven package file from the database and decodes it into a Metadata object.
152148
// Returns the associated PackageFile, Metadata, and any error encountered during processing.
153-
func parseMetadata(sess *xorm.Session, snapshot *mavenPackageResult) (*packages.PackageFile, *Metadata, error) {
154-
ctx := context.Background()
155-
149+
func parseMetadata(ctx context.Context, snapshot *mavenPackageResult) (*packages.PackageFile, *Metadata, error) {
156150
var pf packages.PackageFile
157-
found, err := sess.Table(pf).
151+
found, err := db.GetEngine(ctx).Table(pf).
158152
Where("version_id = ?", snapshot.PackageFile.VersionID). // still the old id
159153
And("lower_name = ?", "maven-metadata.xml").
160154
Get(&pf)
@@ -183,7 +177,7 @@ func parseMetadata(sess *xorm.Session, snapshot *mavenPackageResult) (*packages.
183177

184178
// processPackageVersions processes Maven package versions by updating metadata or inserting new records as necessary.
185179
// It avoids redundant updates by tracking already processed versions using a map. Returns an error on failure.
186-
func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) error {
180+
func processPackageVersions(ctx context.Context, results []*mavenPackageResult) error {
187181
processedVersion := make(map[string]int64)
188182

189183
for _, r := range results {
@@ -196,14 +190,14 @@ func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) e
196190

197191
// for non collisions, just update the metadata
198192
if r.PackageVersion.PackageID == r.Package.ID {
199-
if _, err := sess.ID(r.PackageVersion.ID).Cols("metadata_json").Update(r.PackageVersion); err != nil {
193+
if _, err := db.GetEngine(ctx).ID(r.PackageVersion.ID).Cols("metadata_json").Update(r.PackageVersion); err != nil {
200194
return err
201195
}
202196
} else {
203197
log.Info("Create new maven package version for %s:%s", r.PackageName, r.PackageVersion.Version)
204198
r.PackageVersion.ID = 0
205199
r.PackageVersion.PackageID = r.Package.ID
206-
if _, err := sess.Insert(r.PackageVersion); err != nil {
200+
if _, err := db.GetEngine(ctx).Insert(r.PackageVersion); err != nil {
207201
return err
208202
}
209203
}
@@ -216,10 +210,9 @@ func processPackageVersions(results []*mavenPackageResult, sess *xorm.Session) e
216210

217211
// getMavenPackageResultsToUpdate retrieves Maven package results that need updates based on the owner ID.
218212
// It processes POM metadata, fixes package inconsistencies, and filters corrupted package versions.
219-
func getMavenPackageResultsToUpdate(sess *xorm.Session, ownerID *int64) ([]*mavenPackageResult, error) {
220-
ctx := context.Background()
213+
func getMavenPackageResultsToUpdate(ctx context.Context, ownerID *int64) ([]*mavenPackageResult, error) {
221214
var candidates []*mavenPackageResult
222-
if err := sess.
215+
if err := db.GetEngine(ctx).
223216
Table("package_file").
224217
Select("package_file.*, package_version.*, package.*").
225218
Join("INNER", "package_version", "package_version.id = package_file.version_id").
@@ -265,7 +258,7 @@ func getMavenPackageResultsToUpdate(sess *xorm.Session, ownerID *int64) ([]*mave
265258

266259
// resolvePackageCollisions handles name collisions by keeping the first existing record and inserting new Package records for subsequent collisions.
267260
// Returns a map from PackageName to its resolved Package.ID.
268-
func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session) error {
261+
func resolvePackageCollisions(ctx context.Context, results []*mavenPackageResult) error {
269262
// Group new names by lowerName
270263
collisions := make(map[string][]string)
271264
for _, r := range results {
@@ -292,15 +285,15 @@ func resolvePackageCollisions(results []*mavenPackageResult, sess *xorm.Session)
292285
} else if list[0] == r.PackageName {
293286
pkgIDByName[r.PackageName] = r.Package.ID
294287

295-
if _, err = sess.ID(r.Package.ID).Cols("name", "lower_name").Update(r.Package); err != nil {
288+
if _, err = db.GetEngine(ctx).ID(r.Package.ID).Cols("name", "lower_name").Update(r.Package); err != nil {
296289
return err
297290
}
298291
// create a new entry
299292
} else {
300293
log.Info("Create new maven package for %s", r.Package.Name)
301294

302295
r.Package.ID = 0
303-
if _, err = sess.Insert(r.Package); err != nil {
296+
if _, err = db.GetEngine(ctx).Insert(r.Package); err != nil {
304297
return err
305298
}
306299

0 commit comments

Comments
 (0)