Database migrations run in seperate sessions and commit on success right away (#1822)

This isolates single migration tasks from each other.
The migration itself is now not atomic anymore but each single migration
now on it's own.
This takes load away from databases, as new sessions have a committed
schema available.

We also disable xorm.cache, as the speed improvements are minor but
invalid cache caused by schema changes did happen already in the past.

---------
Reverts #1817
Closes #1821

---------

Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
qwerty287 2023-06-06 03:27:17 +02:00 committed by GitHub
parent f81b447638
commit b82ed13586
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 8 deletions

View file

@ -18,9 +18,22 @@ import (
"xorm.io/xorm"
)
type oldStep017 struct {
ID int64 `xorm:"pk autoincr 'step_id'"`
Machine string `xorm:"step_machine"`
}
func (oldStep017) TableName() string {
return "steps"
}
var removeMachineCol = task{
name: "remove-machine-col",
fn: func(sess *xorm.Session) error {
// make sure step_machine column exists
if err := sess.Sync(new(oldStep017)); err != nil {
return err
}
return dropTableColumns(sess, "steps", "step_machine")
},
}

View file

@ -15,6 +15,7 @@
package migration
import (
"errors"
"fmt"
"reflect"
@ -25,7 +26,7 @@ import (
)
// APPEND NEW MIGRATIONS
// they are executed in order and if one fails woodpecker will try to rollback and quits
// they are executed in order and if one fails woodpecker will try to rollback that specific one and quits
var migrationTasks = []*task{
&legacy2Xorm,
&alterTableReposDropFallback,
@ -93,6 +94,8 @@ func initNew(sess *xorm.Session) error {
}
func Migrate(e *xorm.Engine) error {
e.SetDisableGlobalCache(true)
if err := e.Sync(new(migrations)); err != nil {
return err
}
@ -116,26 +119,24 @@ func Migrate(e *xorm.Engine) error {
return sess.Commit()
}
if err := runTasks(sess, migrationTasks); err != nil {
return err
}
if err := sess.Commit(); err != nil {
return err
}
if err := e.ClearCache(allBeans...); err != nil {
if err := runTasks(e, migrationTasks); err != nil {
return err
}
e.SetDisableGlobalCache(false)
return syncAll(e)
}
func runTasks(sess *xorm.Session, tasks []*task) error {
func runTasks(e *xorm.Engine, tasks []*task) error {
// cache migrations in db
migCache := make(map[string]bool)
var migList []*migrations
if err := sess.Find(&migList); err != nil {
if err := e.Find(&migList); err != nil {
return err
}
for i := range migList {
@ -149,9 +150,18 @@ func runTasks(sess *xorm.Session, tasks []*task) error {
}
log.Trace().Msgf("start migration task '%s'", task.name)
sess := e.NewSession().NoCache()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
if task.fn != nil {
if err := task.fn(sess); err != nil {
if err2 := sess.Rollback(); err2 != nil {
err = errors.Join(err, err2)
}
if task.required {
return err
}
@ -166,6 +176,10 @@ func runTasks(sess *xorm.Session, tasks []*task) error {
if _, err := sess.Insert(&migrations{task.name}); err != nil {
return err
}
if err := sess.Commit(); err != nil {
return err
}
migCache[task.name] = true
}
return nil