code.gitea.io/gitea@v1.21.7/services/actions/clear_tasks.go (about) 1 // Copyright 2022 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package actions 5 6 import ( 7 "context" 8 "fmt" 9 "time" 10 11 actions_model "code.gitea.io/gitea/models/actions" 12 "code.gitea.io/gitea/models/db" 13 "code.gitea.io/gitea/modules/actions" 14 "code.gitea.io/gitea/modules/log" 15 "code.gitea.io/gitea/modules/setting" 16 "code.gitea.io/gitea/modules/timeutil" 17 ) 18 19 // StopZombieTasks stops the task which have running status, but haven't been updated for a long time 20 func StopZombieTasks(ctx context.Context) error { 21 return stopTasks(ctx, actions_model.FindTaskOptions{ 22 Status: actions_model.StatusRunning, 23 UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.ZombieTaskTimeout).Unix()), 24 }) 25 } 26 27 // StopEndlessTasks stops the tasks which have running status and continuous updates, but don't end for a long time 28 func StopEndlessTasks(ctx context.Context) error { 29 return stopTasks(ctx, actions_model.FindTaskOptions{ 30 Status: actions_model.StatusRunning, 31 StartedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.EndlessTaskTimeout).Unix()), 32 }) 33 } 34 35 func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { 36 tasks, err := actions_model.FindTasks(ctx, opts) 37 if err != nil { 38 return fmt.Errorf("find tasks: %w", err) 39 } 40 41 jobs := make([]*actions_model.ActionRunJob, 0, len(tasks)) 42 for _, task := range tasks { 43 if err := db.WithTx(ctx, func(ctx context.Context) error { 44 if err := actions_model.StopTask(ctx, task.ID, actions_model.StatusFailure); err != nil { 45 return err 46 } 47 if err := task.LoadJob(ctx); err != nil { 48 return err 49 } 50 jobs = append(jobs, task.Job) 51 return nil 52 }); err != nil { 53 log.Warn("Cannot stop task %v: %v", task.ID, err) 54 continue 55 } 56 57 remove, err := actions.TransferLogs(ctx, task.LogFilename) 58 if err != nil { 59 log.Warn("Cannot transfer logs of task %v: %v", task.ID, err) 60 continue 61 } 62 task.LogInStorage = true 63 if err := actions_model.UpdateTask(ctx, task, "log_in_storage"); err != nil { 64 log.Warn("Cannot update task %v: %v", task.ID, err) 65 continue 66 } 67 remove() 68 } 69 70 CreateCommitStatus(ctx, jobs...) 71 72 return nil 73 } 74 75 // CancelAbandonedJobs cancels the jobs which have waiting status, but haven't been picked by a runner for a long time 76 func CancelAbandonedJobs(ctx context.Context) error { 77 jobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{ 78 Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked}, 79 UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.AbandonedJobTimeout).Unix()), 80 }) 81 if err != nil { 82 log.Warn("find abandoned tasks: %v", err) 83 return err 84 } 85 86 now := timeutil.TimeStampNow() 87 for _, job := range jobs { 88 job.Status = actions_model.StatusCancelled 89 job.Stopped = now 90 if err := db.WithTx(ctx, func(ctx context.Context) error { 91 _, err := actions_model.UpdateRunJob(ctx, job, nil, "status", "stopped") 92 return err 93 }); err != nil { 94 log.Warn("cancel abandoned job %v: %v", job.ID, err) 95 // go on 96 } 97 CreateCommitStatus(ctx, job) 98 } 99 100 return nil 101 }