diff --git a/app/models/question.rb b/app/models/question.rb index 12e9909d77..39c04546c3 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -33,6 +33,15 @@ class Question < Annotation # Used to authorize the transitions attr_accessor :transition_to, :transition_from + def self.reset_in_progress(id) + return unless exists?(id) + + question = find(id) + return unless question.question_state == 'in_progress' + + question.update(question_state: 'unanswered') + end + def to_partial_path 'annotations/annotation' end @@ -58,15 +67,9 @@ def clear_transition @transition_from = nil end - def reset_in_progress - return unless question_state == 'in_progress' - - update(question_state: 'unanswered') - end - def schedule_reset_in_progress return unless question_state == 'in_progress' - delay(run_at: 1.hour.from_now).reset_in_progress + Question.delay(run_at: 1.hour.from_now).reset_in_progress(id) end end diff --git a/test/controllers/annotations_controller_test.rb b/test/controllers/annotations_controller_test.rb index 894607a2e2..1edd92053f 100644 --- a/test/controllers/annotations_controller_test.rb +++ b/test/controllers/annotations_controller_test.rb @@ -469,16 +469,20 @@ def setup } assert_response :forbidden - # In progress -> answered - question = create :question, submission: @submission, question_state: :in_progress - patch annotation_path(question), params: { - from: question.question_state, - question: { - question_state: :answered - }, - format: :json - } - assert_response :ok + # without delayed jobs, in progress is automatically reset to unanswered + with_delayed_jobs do + # In progress -> answered + question = create :question, submission: @submission, question_state: :in_progress + patch annotation_path(question), params: { + from: question.question_state, + question: { + question_state: :answered + }, + format: :json + } + assert_response :ok + end + run_delayed_jobs end test 'questions can transition from in_progress' do diff --git a/test/models/annotation_test.rb b/test/models/annotation_test.rb index 8e4523c9f5..7958146864 100644 --- a/test/models/annotation_test.rb +++ b/test/models/annotation_test.rb @@ -154,4 +154,19 @@ class AnnotationTest < ActiveSupport::TestCase run_delayed_jobs assert q.reload.answered? end + + test 'delayed job should not crash if question is deleted before execution' do + q = create :question, submission: @submission, user: @student + assert q.unanswered? + + with_delayed_jobs do + q.update(question_state: :in_progress) + assert q.reload.in_progress? + q.destroy + end + + assert_nil Question.find_by(id: q.id) + + run_delayed_jobs + end end diff --git a/test/testhelpers/delayed_job_helper.rb b/test/testhelpers/delayed_job_helper.rb index a15b198054..b0337dbd3e 100644 --- a/test/testhelpers/delayed_job_helper.rb +++ b/test/testhelpers/delayed_job_helper.rb @@ -11,6 +11,9 @@ def with_delayed_jobs end def run_delayed_jobs - Delayed::Job.find_each(batch_size: 100) { |d| Delayed::Worker.new.run(d) } + Delayed::Job.find_each(batch_size: 100) do |d| + Delayed::Worker.new.run(d) + assert_nil d.last_error + end end end