Class: BenefitsIntakeRemediationStatusJob
- Inherits:
-
Object
- Object
- BenefitsIntakeRemediationStatusJob
- Includes:
- Sidekiq::Job
- Defined in:
- app/sidekiq/benefits_intake_remediation_status_job.rb
Overview
Reporting job for Lighthouse Benefit Intake Failures
Constant Summary collapse
- STATS_KEY =
metrics key
'api.benefits_intake.remediation_status'
- BATCH_SIZE =
job batch size
Settings.lighthouse.benefits_intake.report.batch_size || 1000
Instance Attribute Summary collapse
-
#batch_size ⇒ Object
readonly
private
Returns the value of attribute batch_size.
-
#form_id ⇒ Object
readonly
private
Returns the value of attribute form_id.
-
#total_handled ⇒ Object
readonly
private
Returns the value of attribute total_handled.
Instance Method Summary collapse
-
#batch_process(failures) ⇒ Object
private
perform a bulk_status check in Lighthouse to retrieve current statuses a processing error will abort the job (no retries).
-
#handle_response(response_data, failure_batch) ⇒ Object
private
process response from Lighthouse to update outstanding failures.
-
#initialize(batch_size: BATCH_SIZE) ⇒ BenefitsIntakeRemediationStatusJob
constructor
create an instance.
-
#outstanding_failures(submissions) ⇒ Object
private
determine if a claim has an outstanding failure each claim can have multiple FormSubmission, which can have multiple FormSubmissionAttempt conflate these and search for a non-failure, which rejects the claim from the list.
-
#perform(form_id = nil) ⇒ Object
search all submissions for outstanding failures poll LH endpoint to see if status has changed (case if endpoint had an error initially) report stats on submissions, grouped by form-type.
-
#submission_audit ⇒ Object
private
gather metrics - grouped by form type.
-
#submission_audit_metrics(form_type, unsubmitted, orphaned, failures) ⇒ Object
private
report metrics.
Constructor Details
#initialize(batch_size: BATCH_SIZE) ⇒ BenefitsIntakeRemediationStatusJob
create an instance
19 20 21 22 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 19 def initialize(batch_size: BATCH_SIZE) @batch_size = batch_size @total_handled = 0 end |
Instance Attribute Details
#batch_size ⇒ Object (readonly, private)
Returns the value of attribute batch_size.
49 50 51 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 49 def batch_size @batch_size end |
#form_id ⇒ Object (readonly, private)
Returns the value of attribute form_id.
49 50 51 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 49 def form_id @form_id end |
#total_handled ⇒ Object (readonly, private)
Returns the value of attribute total_handled.
49 50 51 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 49 def total_handled @total_handled end |
Instance Method Details
#batch_process(failures) ⇒ Object (private)
perform a bulk_status check in Lighthouse to retrieve current statuses a processing error will abort the job (no retries)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 72 def batch_process(failures) intake_service = BenefitsIntake::Service.new failures.each_slice(batch_size) do |batch| batch_uuids = batch.map { |submission| submission.latest_attempt&.benefits_intake_uuid } Rails.logger.info('BenefitsIntakeRemediationStatusJob processing batch', batch_uuids:) response = intake_service.bulk_status(uuids: batch_uuids) raise response.body unless response.success? next unless (data = response.body['data']) handle_response(data, batch) end end |
#handle_response(response_data, failure_batch) ⇒ Object (private)
process response from Lighthouse to update outstanding failures
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 93 def handle_response(response_data, failure_batch) response_data.each do |submission| uuid = submission['id'] form_submission = failure_batch.find do |submission_from_db| submission_from_db.latest_attempt&.benefits_intake_uuid == uuid end form_submission.form_type form_submission_attempt = form_submission.form_submission_attempts.last # https://developer.va.gov/explore/api/benefits-intake/docs status = submission.dig('attributes', 'status') lighthouse_updated_at = submission.dig('attributes', 'updated_at') if status == 'vbms' # submission was successfully uploaded into a Veteran's eFolder within VBMS form_submission_attempt.update(lighthouse_updated_at:) form_submission_attempt.remediate! end @total_handled = total_handled + 1 end end |
#outstanding_failures(submissions) ⇒ Object (private)
determine if a claim has an outstanding failure each claim can have multiple FormSubmission, which can have multiple FormSubmissionAttempt conflate these and search for a non-failure, which rejects the claim from the list
57 58 59 60 61 62 63 64 65 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 57 def outstanding_failures(submissions) failures = submissions.group_by(&:saved_claim_id) failures.map do |_claim_id, fs| fs.sort_by!(&:created_at) attempts = fs.map(&:form_submission_attempts).flatten.sort_by(&:created_at) not_failure = attempts.find { |att| att.aasm_state != 'failure' } not_failure ? nil : fs.last end.compact end |
#perform(form_id = nil) ⇒ Object
search all submissions for outstanding failures poll LH endpoint to see if status has changed (case if endpoint had an error initially) report stats on submissions, grouped by form-type
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 27 def perform(form_id = nil) Rails.logger.info('BenefitsIntakeRemediationStatusJob started') form_submissions = FormSubmission.includes(:form_submission_attempts) failures = outstanding_failures(form_submissions.all) # filter running this job to a specific form_id/form_type @form_id = form_id failures.select! { |f| f.form_type == form_id } if form_id batch_process(failures) unless failures.empty? submission_audit Rails.logger.info('BenefitsIntakeRemediationStatusJob ended', total_handled:) rescue => e # catch and log, but not re-raise to avoid sidekiq exhaustion alerts Rails.logger.error('BenefitsIntakeRemediationStatusJob ERROR', class: self.class.name, message: e.) end |
#submission_audit ⇒ Object (private)
gather metrics - grouped by form type
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 118 def submission_audit # requery form_submissions in case there was an update form_submissions = FormSubmission.includes(:form_submission_attempts) form_submission_groups = form_submissions.all.group_by(&:form_type) form_submission_groups.each do |form_type, submissions| next if form_id && form_id != form_type fs_saved_claim_ids = submissions.map(&:saved_claim_id).uniq.compact next unless (earliest = fs_saved_claim_ids.min) claims = SavedClaim.where(form_id: form_type).where('id >= ?', earliest) claim_ids = claims.map(&:id).uniq unsubmitted = claim_ids - fs_saved_claim_ids orphaned = fs_saved_claim_ids - claim_ids failures = outstanding_failures(submissions) failures.map! do |fs| { claim_id: fs.saved_claim_id, uuid: fs.latest_attempt.benefits_intake_uuid, error_message: fs.latest_attempt. } end submission_audit_metrics(form_type, unsubmitted, orphaned, failures) end end |
#submission_audit_metrics(form_type, unsubmitted, orphaned, failures) ⇒ Object (private)
report metrics
151 152 153 154 155 156 157 |
# File 'app/sidekiq/benefits_intake_remediation_status_job.rb', line 151 def submission_audit_metrics(form_type, unsubmitted, orphaned, failures) audit_log = "BenefitsIntakeRemediationStatusJob submission audit #{form_type}" StatsD.gauge("#{STATS_KEY}.unsubmitted_claims", unsubmitted.length, tags: ["form_id:#{form_type}"]) StatsD.gauge("#{STATS_KEY}.orphaned_submissions", orphaned.length, tags: ["form_id:#{form_type}"]) StatsD.gauge("#{STATS_KEY}.outstanding_failures", failures.length, tags: ["form_id:#{form_type}"]) Rails.logger.info(audit_log, form_id: form_type, unsubmitted:, orphaned:, failures:) end |