You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

clear_tasks.go 3.0KB

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