From d4544ecffb2a4ac9b4c935fedfb12e360543ee1c Mon Sep 17 00:00:00 2001 From: Samuel Cochran Date: Mon, 17 Jul 2023 13:22:18 +1000 Subject: [PATCH] Allow resuming errored task runs Allows clicking "Resume" on an errored run to resume the run from the errored point, preserving progress. This is useful for transient errors, like those from infrastructure, which have not yet been anticipated. --- .../maintenance_tasks/run_status_validator.rb | 3 +++ app/views/maintenance_tasks/runs/_run.html.erb | 2 ++ test/system/maintenance_tasks/runs_test.rb | 5 +++++ .../maintenance_tasks/run_status_validator_test.rb | 12 ++++++++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/validators/maintenance_tasks/run_status_validator.rb b/app/validators/maintenance_tasks/run_status_validator.rb index f56e95386..c4a30637b 100644 --- a/app/validators/maintenance_tasks/run_status_validator.rb +++ b/app/validators/maintenance_tasks/run_status_validator.rb @@ -60,6 +60,9 @@ class RunStatusValidator < ActiveModel::Validator # interrupted -> errored occurs when the task is deleted while it is # interrupted. "interrupted" => ["running", "pausing", "cancelling", "errored"], + # errored -> enqueued occurs when the task is retried after encounting an + # error. + "errored" => ["enqueued"], } # Validate whether a transition from one Run status diff --git a/app/views/maintenance_tasks/runs/_run.html.erb b/app/views/maintenance_tasks/runs/_run.html.erb index f70496d96..bbda4b321 100644 --- a/app/views/maintenance_tasks/runs/_run.html.erb +++ b/app/views/maintenance_tasks/runs/_run.html.erb @@ -22,6 +22,8 @@ <% if run.paused? %> <%= button_to 'Resume', resume_task_run_path(@task, run), method: :put, class: 'button is-primary', disabled: @task.deleted? %> <%= button_to 'Cancel', cancel_task_run_path(@task, run), method: :put, class: 'button is-danger' %> + <% elsif run.errored? %> + <%= button_to 'Resume', resume_task_run_path(@task, run), method: :put, class: 'button is-primary', disabled: @task.deleted? %> <% elsif run.cancelling? %> <% if run.stuck? %> <%= button_to 'Cancel', cancel_task_run_path(@task, run), method: :put, class: 'button is-danger', disabled: @task.deleted? %> diff --git a/test/system/maintenance_tasks/runs_test.rb b/test/system/maintenance_tasks/runs_test.rb index 54f05e569..21b16eb38 100644 --- a/test/system/maintenance_tasks/runs_test.rb +++ b/test/system/maintenance_tasks/runs_test.rb @@ -191,6 +191,11 @@ class RunsTest < ApplicationSystemTestCase assert_text "ArgumentError" assert_text "Something went wrong" assert_text "app/tasks/maintenance/error_task.rb:10:in `process'" + + click_on "Resume" + + assert_text "Enqueued" + assert_text "Waiting to start." end test "errors for double enqueue are shown" do diff --git a/test/validators/maintenance_tasks/run_status_validator_test.rb b/test/validators/maintenance_tasks/run_status_validator_test.rb index ee617c7db..c584605cd 100644 --- a/test/validators/maintenance_tasks/run_status_validator_test.rb +++ b/test/validators/maintenance_tasks/run_status_validator_test.rb @@ -21,7 +21,7 @@ class RunStatusValidatorTest < ActiveSupport::TestCase assert_no_invalid_transitions([:enqueued, :interrupted], :running) end - test "run can go from paused to enqueued" do + test "run can go from paused or errored to enqueued" do paused_run = Run.create!( task_name: "Maintenance::UpdatePostsTask", status: :paused, @@ -30,7 +30,15 @@ class RunStatusValidatorTest < ActiveSupport::TestCase assert paused_run.valid? - assert_no_invalid_transitions([:paused], :enqueued) + errored_run = Run.create!( + task_name: "Maintenance::UpdatePostsTask", + status: :errored, + ) + errored_run.status = :enqueued + + assert errored_run.valid? + + assert_no_invalid_transitions([:paused, :errored], :enqueued) end test "run can go from running, cancelling or pausing to succeeded" do