summaryrefslogtreecommitdiffstats
path: root/services/task
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2023-05-11 16:25:46 +0800
committerGitHub <noreply@github.com>2023-05-11 08:25:46 +0000
commitf6e029e6c7849d4361abf7f1d749b5d528364ac4 (patch)
treeaf285dd000dc48e4e94e717cf61a8b2437e99beb /services/task
parent58dfaf3a75a097088376a9c221784b3675ac9c48 (diff)
downloadgitea-f6e029e6c7849d4361abf7f1d749b5d528364ac4.tar.gz
gitea-f6e029e6c7849d4361abf7f1d749b5d528364ac4.zip
Make repo migration cancelable and fix various bugs (#24605)
Replace #12917 Close #24601 Close #12845 ![image](https://github.com/go-gitea/gitea/assets/2114189/39378118-064d-40fb-8396-4579ebf33917) ![image](https://github.com/go-gitea/gitea/assets/2114189/faf37418-191c-46a6-90a8-353141e00e2d) ![image](https://github.com/go-gitea/gitea/assets/2114189/fdc8ee4d-125f-4737-9990-89bcdf9eb388) ![image](https://github.com/go-gitea/gitea/assets/2114189/9a3bd2c2-fe20-4011-81f0-990ed869d139) --------- Co-authored-by: Yarden Shoham <git@yardenshoham.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Giteabot <teabot@gitea.io>
Diffstat (limited to 'services/task')
-rw-r--r--services/task/migrate.go49
-rw-r--r--services/task/task.go2
2 files changed, 32 insertions, 19 deletions
diff --git a/services/task/migrate.go b/services/task/migrate.go
index 03d083e596..98454482b5 100644
--- a/services/task/migrate.go
+++ b/services/task/migrate.go
@@ -7,8 +7,8 @@ import (
"errors"
"fmt"
"strings"
+ "time"
- "code.gitea.io/gitea/models"
admin_model "code.gitea.io/gitea/models/admin"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
@@ -28,13 +28,13 @@ import (
func handleCreateError(owner *user_model.User, err error) error {
switch {
case repo_model.IsErrReachLimitOfRepo(err):
- return fmt.Errorf("You have already reached your limit of %d repositories", owner.MaxCreationLimit())
+ return fmt.Errorf("you have already reached your limit of %d repositories", owner.MaxCreationLimit())
case repo_model.IsErrRepoAlreadyExist(err):
- return errors.New("The repository name is already used")
+ return errors.New("the repository name is already used")
case db.IsErrNameReserved(err):
- return fmt.Errorf("The repository name '%s' is reserved", err.(db.ErrNameReserved).Name)
+ return fmt.Errorf("the repository name '%s' is reserved", err.(db.ErrNameReserved).Name)
case db.IsErrNamePatternNotAllowed(err):
- return fmt.Errorf("The pattern '%s' is not allowed in a repository name", err.(db.ErrNamePatternNotAllowed).Pattern)
+ return fmt.Errorf("the pattern '%s' is not allowed in a repository name", err.(db.ErrNamePatternNotAllowed).Pattern)
default:
return err
}
@@ -57,22 +57,17 @@ func runMigrateTask(t *admin_model.Task) (err error) {
log.Error("FinishMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d] failed: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, err)
}
+ log.Error("runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d] failed: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, err)
+
t.EndTime = timeutil.TimeStampNow()
t.Status = structs.TaskStatusFailed
t.Message = err.Error()
- // Ensure that the repo loaded before we zero out the repo ID from the task - thus ensuring that we can delete it
- _ = t.LoadRepo()
- t.RepoID = 0
- if err := t.UpdateCols("status", "errors", "repo_id", "end_time"); err != nil {
+ if err := t.UpdateCols("status", "message", "end_time"); err != nil {
log.Error("Task UpdateCols failed: %v", err)
}
- if t.Repo != nil {
- if errDelete := models.DeleteRepository(t.Doer, t.OwnerID, t.Repo.ID); errDelete != nil {
- log.Error("DeleteRepository: %v", errDelete)
- }
- }
+ // then, do not delete the repository, otherwise the users won't be able to see the last error
}()
if err = t.LoadRepo(); err != nil {
@@ -100,7 +95,7 @@ func runMigrateTask(t *admin_model.Task) (err error) {
opts.MigrateToRepoID = t.RepoID
pm := process.GetManager()
- ctx, _, finished := pm.AddContext(graceful.GetManager().ShutdownContext(), fmt.Sprintf("MigrateTask: %s/%s", t.Owner.Name, opts.RepoName))
+ ctx, cancel, finished := pm.AddContext(graceful.GetManager().ShutdownContext(), fmt.Sprintf("MigrateTask: %s/%s", t.Owner.Name, opts.RepoName))
defer finished()
t.StartTime = timeutil.TimeStampNow()
@@ -109,6 +104,23 @@ func runMigrateTask(t *admin_model.Task) (err error) {
return
}
+ // check whether the task should be canceled, this goroutine is also managed by process manager
+ go func() {
+ for {
+ select {
+ case <-time.After(2 * time.Second):
+ case <-ctx.Done():
+ return
+ }
+ task, _ := admin_model.GetMigratingTask(t.RepoID)
+ if task != nil && task.Status != structs.TaskStatusRunning {
+ log.Debug("MigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d] is canceled due to status is not 'running'", t.ID, t.DoerID, t.RepoID, t.OwnerID)
+ cancel()
+ return
+ }
+ }
+ }()
+
t.Repo, err = migrations.MigrateRepository(ctx, t.Doer, t.Owner.Name, *opts, func(format string, args ...interface{}) {
message := admin_model.TranslatableMessage{
Format: format,
@@ -118,13 +130,14 @@ func runMigrateTask(t *admin_model.Task) (err error) {
t.Message = string(bs)
_ = t.UpdateCols("message")
})
+
if err == nil {
log.Trace("Repository migrated [%d]: %s/%s", t.Repo.ID, t.Owner.Name, t.Repo.Name)
return
}
if repo_model.IsErrRepoAlreadyExist(err) {
- err = errors.New("The repository name is already used")
+ err = errors.New("the repository name is already used")
return
}
@@ -132,9 +145,9 @@ func runMigrateTask(t *admin_model.Task) (err error) {
err = util.SanitizeErrorCredentialURLs(err)
if strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "could not read Username") {
- return fmt.Errorf("Authentication failed: %w", err)
+ return fmt.Errorf("authentication failed: %w", err)
} else if strings.Contains(err.Error(), "fatal:") {
- return fmt.Errorf("Migration failed: %w", err)
+ return fmt.Errorf("migration failed: %w", err)
}
// do not be tempted to coalesce this line with the return
diff --git a/services/task/task.go b/services/task/task.go
index 4f1ba3a60b..493586a645 100644
--- a/services/task/task.go
+++ b/services/task/task.go
@@ -95,7 +95,7 @@ func CreateMigrateTask(doer, u *user_model.User, opts base.MigrateOptions) (*adm
DoerID: doer.ID,
OwnerID: u.ID,
Type: structs.TaskTypeMigrateRepo,
- Status: structs.TaskStatusQueue,
+ Status: structs.TaskStatusQueued,
PayloadContent: string(bs),
}