diff --git a/app/models/concerns/asyncable.rb b/app/models/concerns/asyncable.rb index 953ffc34f35..e1e0606e1c3 100644 --- a/app/models/concerns/asyncable.rb +++ b/app/models/concerns/asyncable.rb @@ -28,6 +28,7 @@ module Asyncable # These column names can be overridden in consuming classes as needed. class_methods do REQUIRES_PROCESSING_WINDOW_DAYS = 4 + EXPIRATION_WINDOW_BUFFER_HOURS = 1 DEFAULT_REQUIRES_PROCESSING_RETRY_WINDOW_HOURS = 3 PROCESS_DELAY_VBMS_OFFSET_HOURS = 7 @@ -205,7 +206,7 @@ def expired_without_processing? last_submitted = self[self.class.last_submitted_at_column] return false unless last_submitted - last_submitted < self.class.requires_processing_until + last_submitted < (self.class.requires_processing_until + self.class::EXPIRATION_WINDOW_BUFFER_HOURS.hours) end def submitted_and_ready? diff --git a/spec/models/concerns/timeable_task_spec.rb b/spec/models/concerns/timeable_task_spec.rb index 94e3893aa58..2d37fa2ae68 100644 --- a/spec/models/concerns/timeable_task_spec.rb +++ b/spec/models/concerns/timeable_task_spec.rb @@ -37,6 +37,21 @@ def timer_ends_at end end + class EdgeCaseTimedTask < Task + include TimeableTask + include CurrentDate + + def when_timer_ends; end + + def timer_ends_at + # Our task timer job runs every hour. On occasion we create task timers that should have expired 3.99999 days ago + # so they are not caught by the initial expired_without_processing? check when they are created. However, by the + # time the job has run, the task should have expired 4.000001 days ago and falls out of our + # expired_without_processing scope. See https://github.com/department-of-veterans-affairs/caseflow/issues/15245 + 4.days.ago + 30.minutes + end + end + before do Timecop.freeze(now) end @@ -54,13 +69,26 @@ def timer_ends_at expect(timers.first.submitted_at).to eq(task.timer_ends_at) end - it "queues itself immediately when the delay is in the past" do - task = OldTimedTask.create!(appeal: appeal, assigned_to: Bva.singleton) - timers = TaskTimer.where(task: task) - expect(timers.length).to eq(1) - expect(timers.first.submitted_and_ready?).to eq(true) - expect(timers.first.submitted_at).to eq(task.timer_ends_at) - expect(timers.first.last_submitted_at).to eq(now) + shared_examples "resets the timer" do + it "queues itself immediately when the delay is in the past" do + timers = TaskTimer.where(task: task) + expect(timers.length).to eq(1) + expect(timers.first.submitted_and_ready?).to eq(true) + expect(timers.first.submitted_at).to eq(task.timer_ends_at) + expect(timers.first.last_submitted_at).to eq(now) + end + end + + context "when the delay is in the past" do + let(:task) { OldTimedTask.create!(appeal: appeal, assigned_to: Bva.singleton) } + + it_behaves_like "resets the timer" + end + + context "when the delay is judge barely less than four days in the past" do + let(:task) { EdgeCaseTimedTask.create!(appeal: appeal, assigned_to: Bva.singleton) } + + it_behaves_like "resets the timer" end context "when not correctly configured" do