Skip to content

Commit

Permalink
Migrate task timer Looker view to data integrity checker (#12428)
Browse files Browse the repository at this point in the history
Resolves #12111 

### Description
Ports the old Looker SQL snippet to a modern Query object. The SQL is included for reference.
  • Loading branch information
kevmo authored Mar 31, 2020
1 parent e91b9bd commit 070a6db
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 20 deletions.
11 changes: 6 additions & 5 deletions .reek.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,26 +148,27 @@ detectors:
- ETL::Builder#last_built
- ETL::Syncer#filter?
- ETL::TaskSyncer#filter?
- Fakes::BGSService
- Fakes::PexipService
- HearingAdminActionVerifyAddressTask#available_hearing_admin_actions
- HearingDispositionChangeJob
- Helpers::AppealHearingHelper#available_hearing_locations
- Helpers::AppealHearingHelper#hearings
- JudgeLegacyDecisionReviewTask#review_action
- LatestRatingDisabilityEvaluation#latest_disability_evaluation
- LegacyDocket#age_of_n_oldest_priority_appeals
- JudgeLegacyDecisionReviewTask#review_action
- OrganizationOnHoldTasksTab#name
- OrganizationTrackingTasksTab#column_names
- Fakes::BGSService
- Fakes::PexipService
- VBMSCaseflowLogger#log
- PendingIncompleteAndUncancelledTaskTimersQuery#call
- Reporter#average
- Reporter#median
- Reporter#seconds_to_hms
- Reporter#percent
- ScheduleHearingTaskPager#sorted_tasks
- VBMSCaseflowLogger#log
- VirtualHearings::ExternalLinkHelper#external_link
- VirtualHearings::ExternalLinkHelper#phone_link
- VirtualHearings::VeteranNameHelper#formatted_veteran_name
- ScheduleHearingTaskPager#sorted_tasks

### Directory specific configuration
# You can configure smells on a per-directory base.
Expand Down
1 change: 1 addition & 0 deletions app/jobs/data_integrity_checks_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class DataIntegrityChecksJob < CaseflowJob
LegacyAppealsWithNoVacolsCase
OpenHearingTasksWithoutActiveDescendantsChecker
OpenTasksWithClosedAtChecker
PendingIncompleteAndUncancelledTaskTimersChecker
ReviewsWithDuplicateEpErrorChecker
StuckAppealsChecker
UntrackedLegacyAppealsChecker
Expand Down
32 changes: 17 additions & 15 deletions app/models/task_timer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@ class TaskTimer < CaseflowRecord
belongs_to :task
include Asyncable

def veteran
task.appeal.veteran
end
class << self
def requires_processing
# Only process timers for tasks that are active.
# Inline original definition of the requires_processing function due to limitations of mixins.
with_active_tasks.processable.attemptable.unexpired.order_by_oldest_submitted
end

def self.requires_processing
# Only process timers for tasks that are active.
# Inline original definition of the requires_processing function due to limitations of mixins.
with_active_tasks.processable.attemptable.unexpired.order_by_oldest_submitted
end
def requires_cancelling
with_closed_tasks.processable.order_by_oldest_submitted
end

def self.requires_cancelling
with_closed_tasks.processable.order_by_oldest_submitted
end
def with_active_tasks
includes(:task).where.not(tasks: { status: Task.closed_statuses })
end

def self.with_active_tasks
includes(:task).where.not(tasks: { status: Task.closed_statuses })
def with_closed_tasks
includes(:task).where(tasks: { status: Task.closed_statuses })
end
end

def self.with_closed_tasks
includes(:task).where(tasks: { status: Task.closed_statuses })
def veteran
task.appeal.veteran
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen-string-literal: true

class PendingIncompleteAndUncancelledTaskTimersQuery
def call
TaskTimer.processable
.where("task_timers.created_at < ? AND task_timers.submitted_at < ?",
Time.zone.yesterday, Time.zone.yesterday - 1)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class PendingIncompleteAndUncancelledTaskTimersChecker < DataIntegrityChecker
def call
return if pending_timers.count == 0

add_to_report "#{pending_timers.count} pending and incomplete TaskTimers"
add_to_report "Verify TaskTimerJob is running and check each TaskTimer.error"
pending_timers.each do |timer|
add_to_report "TaskTimer.find(#{timer.id})"
end
end

private

def pending_timers
@pending_timers ||= PendingIncompleteAndUncancelledTaskTimersQuery.new.call
end
end
11 changes: 11 additions & 0 deletions app/sql/task-timer-looker.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
SELECT
DATE(task_timers.created_at ) AS "task_timers.created_date",
task_timers.id AS "task_timers.id",
DATE(task_timers.submitted_at ) AS "task_timers.submitted_date",
DATE(task_timers.attempted_at ) AS "task_timers.attempted_date",
task_timers.task_id AS "task_timers.task_id"
FROM public.task_timers AS task_timers

WHERE ((task_timers.created_at < (DATEADD(day,-1, DATE_TRUNC('day',GETDATE()) )))) AND (task_timers.processed_at IS NULL) AND (task_timers.canceled_at IS NULL) AND ((task_timers.submitted_at < (DATEADD(day,-2, DATE_TRUNC('day',GETDATE()) ))))
ORDER BY 1 DESC
LIMIT 500
9 changes: 9 additions & 0 deletions spec/factories/task_timer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

FactoryBot.define do
factory :task_timer do
association :task, factory: :task
last_submitted_at { Time.zone.now }
submitted_at { Time.zone.now }
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

describe PendingIncompleteAndUncancelledTaskTimersQuery do
describe "#call" do
let(:task) { create(:task) }
let!(:task_timer) do
create(:task_timer, task: task, created_at: 5.days.ago, submitted_at: 6.days.ago)
end
let!(:task_timer2) do
create(:task_timer, task: task)
end

it "finds incomplete task timers" do
expect(subject.call).to eq([task_timer])
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

describe PendingIncompleteAndUncancelledTaskTimersChecker do
describe "#call" do
let(:task) { create(:task) }
let!(:task_timer) do
create(:task_timer, task: task, created_at: 5.days.ago, submitted_at: 6.days.ago)
end
let!(:task_timer2) { create(:task_timer, task: task) }

it "sends a message to Slack when there are pending incomplete and uncancelled Task Timers" do
subject.call

expect(subject.report?).to eq(true)
expect(subject.report).to match("1 pending and incomplete")
expect(subject.slack_channel).to eq("#appeals-job-alerts")
end
end
end

0 comments on commit 070a6db

Please sign in to comment.