Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial 526 form 4142 benefits intake API work #18801

Open
wants to merge 74 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
98b5b0d
Initial 526 form 4142 benefits intake API work
kylesoskin Oct 9, 2024
60e5bd2
Specing out more
kylesoskin Oct 9, 2024
4c68bf8
Rubocop'ing
kylesoskin Oct 9, 2024
a9e2bf2
Renaming to more generic 4142 class
kylesoskin Oct 9, 2024
e2829ef
Moving around
kylesoskin Oct 9, 2024
5b28b45
Moving
kylesoskin Oct 9, 2024
eacb120
adding some testing they are faling due to error with VCR/filenumber …
kylesoskin Oct 9, 2024
b08f2f7
rubocop
kylesoskin Oct 9, 2024
6acea92
Adding additional testing
kylesoskin Oct 9, 2024
165d4a6
Remove debug
kylesoskin Oct 9, 2024
67c19f1
model tests
kylesoskin Oct 9, 2024
9e530c1
More tests
kylesoskin Oct 10, 2024
f6ae257
Rubocop and email and flipper support
kylesoskin Oct 10, 2024
a871cab
Dont need to add to my change linecount
kylesoskin Oct 10, 2024
793a68d
Remove whitespace
kylesoskin Oct 10, 2024
d88fc3d
Removing my own model, using existing FormSubmission/Form526Submission
kylesoskin Oct 16, 2024
5955c9b
altering tests
kylesoskin Oct 16, 2024
397b1e8
Rubocop
kylesoskin Oct 16, 2024
577fbe7
Rubocopin
kylesoskin Oct 16, 2024
bdc1195
Changing to pass
kylesoskin Oct 17, 2024
45e0d62
Undoing db changes no longer needed
kylesoskin Oct 17, 2024
e9114e9
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 17, 2024
8289238
unresolved merge fixes
kylesoskin Oct 17, 2024
86a35ee
Removing benefits intake service class to another PR
kylesoskin Oct 17, 2024
80cf011
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 17, 2024
8d95332
rubocoping
kylesoskin Oct 17, 2024
1b4e5d5
Not sure where this came from but undoing it
kylesoskin Oct 17, 2024
6d14811
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 17, 2024
e71224a
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 17, 2024
df3fb23
Fixing location of bool
kylesoskin Oct 17, 2024
0e5ab0d
Merge branch 'dbex/94144_trigger_email_on_polled_4142_failure' of htt…
kylesoskin Oct 17, 2024
ddf05d0
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 17, 2024
19888ee
Rubocop
kylesoskin Oct 18, 2024
b56dc01
Adding test case for flippers off
kylesoskin Oct 21, 2024
23c52a7
Removing dup let
kylesoskin Oct 21, 2024
039d1ff
fixing tests
kylesoskin Oct 21, 2024
3933f1b
Adding ZSF increments
kylesoskin Oct 21, 2024
a664636
rubocop
kylesoskin Oct 21, 2024
035b497
rubocop
kylesoskin Oct 21, 2024
21575f9
Adding email job statsD
kylesoskin Oct 21, 2024
742c734
Adding service constant
kylesoskin Oct 21, 2024
64630b4
Fixing form num
kylesoskin Oct 21, 2024
2418f16
Rubocop
kylesoskin Oct 21, 2024
64509c0
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 21, 2024
6fabd4f
Removing lines to appease CI/CD
kylesoskin Oct 21, 2024
f15b918
Adding in ZeroSilentFailure Stuff
kylesoskin Oct 22, 2024
9b84326
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 22, 2024
a40c3cd
Truing up with flippers removed upstream
kylesoskin Oct 22, 2024
c8ea3fe
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 22, 2024
e88bc15
Trying to cull lines to appease the line-counter
kylesoskin Oct 22, 2024
404d886
Addressing PR comments
kylesoskin Oct 22, 2024
fee21cb
Correcting wrong variable
kylesoskin Oct 22, 2024
c81a860
Moving around logging var
kylesoskin Oct 22, 2024
0d87bc5
Making a var a constant instead
kylesoskin Oct 22, 2024
2378353
Making more readable
kylesoskin Oct 22, 2024
c5dd50a
Changing instance var to regular var
kylesoskin Oct 22, 2024
07ff2d9
Fixing typo and extra db call
kylesoskin Oct 22, 2024
f9a77e9
Resolving failed test
kylesoskin Oct 23, 2024
753affd
Fixing comment
kylesoskin Oct 23, 2024
06819e2
Dont want to confuse these vars
kylesoskin Oct 23, 2024
79f2f0e
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 23, 2024
d53e240
Fixing test
kylesoskin Oct 23, 2024
af755fb
Adding support for user account id in error message
kylesoskin Oct 24, 2024
0414d9e
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 24, 2024
423def3
Fixing arg
kylesoskin Oct 24, 2024
8bdd2ce
extracting out this code
kylesoskin Oct 24, 2024
3461d4c
Refactoring to less vars
kylesoskin Oct 24, 2024
a1d470c
Fixing test cases
kylesoskin Oct 24, 2024
90fddb0
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 24, 2024
643e726
Spelling mistake
kylesoskin Oct 24, 2024
244f851
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 25, 2024
6ffb51c
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 25, 2024
be2d183
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 25, 2024
a9dad1d
Merge branch 'master' into dbex/94144_trigger_email_on_polled_4142_fa…
kylesoskin Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/models/form526_submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Form526Submission < ApplicationRecord
# MAX_PENDING_TIME aligns with the farthest out expectation given in the LH BI docs,
# plus 1 week to accomodate for edge cases and our sidekiq jobs
MAX_PENDING_TIME = 3.weeks
ZSF_DD_TAG_SERVICE = 'disability-application'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: maybe use docstrings or spell out ZERO_SILENT_FAILUIRES to make sure ZSF is clear to future generations? It's probably already a precedent in the codebase though so maybe too late? 🤷


# used to track in APMs between systems such as Lighthouse
# example: can be used as a search parameter in Datadog
Expand Down
50 changes: 43 additions & 7 deletions app/models/form_submission_attempt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ class FormSubmissionAttempt < ApplicationRecord

event :fail do
after do
form_type = form_submission.form_type
log_info = { form_submission_id:,
benefits_intake_uuid: form_submission&.benefits_intake_uuid,
form_type:,
user_account_uuid: form_submission.user_account_id }
if should_send_simple_forms_email
Rails.logger.info({
message: 'Preparing to send Form Submission Attempt error email',
form_submission_id:,
benefits_intake_uuid: form_submission.benefits_intake_uuid,
form_type: form_submission.form_type
})
simple_forms_enqueue_result_email(:error)
simple_forms_api_email(log_info)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pulling this part out into a method!

elsif form_type == CentralMail::SubmitForm4142Job::FORM4142_FORMSUBMISSION_TYPE
form526_form4142_email(log_info)
end
end

Expand Down Expand Up @@ -80,6 +81,41 @@ def log_status_change

private

def simple_forms_api_email(log_info)
Rails.logger.info('Preparing to send Form Submission Attempt error email', log_info)
simple_forms_enqueue_result_email(:error)
end

def queue_form526_form4142_email(form526_submission_id, log_info)
Rails.logger.info('Queuing Form526:Form4142 failure email to VaNotify',
log_info.merge({ form526_submission_id: }))
jid = EVSS::DisabilityCompensationForm::Form4142DocumentUploadFailureEmail.perform_async(
form526_submission_id
)
Rails.logger.info('Queuing Form526:Form4142 failure email to VaNotify completed',
log_info.merge({ jid:, form526_submission_id: }))
end

def form526_form4142_email(log_info)
if Flipper.enabled?(CentralMail::SubmitForm4142Job::POLLED_FAILURE_EMAIL)
queue_form526_form4142_email(Form526Submission.find_by(saved_claim_id:).id, log_info)
else
Rails.logger.info(
'Would queue EVSS::DisabilityCompensationForm::Form4142DocumentUploadFailureEmail, but flipper is off.',
log_info.merge({ form526_submission_id: })
)
end
rescue => e
cl = caller_locations.first
call_location = ZeroSilentFailures::Monitor::CallLocation.new(
CentralMail::SubmitForm4142Job::FORM4142_DD_ZSF_FUNCTION, cl.path, cl.lineno
)
ZeroSilentFailures::Monitor.new(Form526Submission::ZSF_DD_TAG_SERVICE).log_silent_failure(
log_info.merge({ error_class: e.class, error_message: e.message }),
log_info[:user_account_uuid], call_location:
)
end

def should_send_simple_forms_email
simple_forms_form_number && Flipper.enabled?(:simple_forms_email_notifications)
end
Expand Down
41 changes: 33 additions & 8 deletions app/sidekiq/central_mail/submit_form4142_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
# TODO: Update Namespace once we are 100% done with CentralMail here
module CentralMail
class SubmitForm4142Job < EVSS::DisabilityCompensationForm::Job
INITIAL_FAILURE_EMAIL = :form526_send_4142_failure_notification
POLLING_FLIPPER_KEY = :disability_526_form4142_polling_records
POLLED_FAILURE_EMAIL = :disability_526_form4142_polling_record_failure_email

FORM4142_FORMSUBMISSION_TYPE = "#{Form526Submission::FORM_526}_#{Form526Submission::FORM_4142}".freeze
FORM4142_DD_ZSF_FUNCTION = 'Form 526 Flow - Form 4142 failure email queuing'
extend Logging::ThirdPartyTransaction::MethodWrapper

# this is required to make instance variables available to logs via
Expand Down Expand Up @@ -131,20 +137,39 @@ def lighthouse_service
@lighthouse_service ||= BenefitsIntakeService::Service.new(with_upload_location: true)
end

def upload_to_lighthouse
Rails.logger.info(
'Successful Form4142 Submission to Lighthouse',
{ benefits_intake_uuid: lighthouse_service.uuid, submission_id: @submission_id }
)

payload = {
upload_url: lighthouse_service.location,
def payload_hash(lighthouse_service_location)
{
upload_url: lighthouse_service_location,
file: { file: @pdf_path, file_name: @pdf_path.split('/').last },
metadata: generate_metadata.to_json,
attachments: []
}
end

def upload_to_lighthouse
log_info = { benefits_intake_uuid: lighthouse_service.uuid, submission_id: @submission_id }

Rails.logger.info(
'Successful Form4142 Upload Intake UUID acquired from Lighthouse',
log_info
)

payload = payload_hash(lighthouse_service.location)
lighthouse_service.upload_doc(**payload)

if Flipper.enabled?(POLLING_FLIPPER_KEY)
form526_submission = Form526Submission.find(@submission_id)
form_submission = FormSubmission.create(
form_type: FORM4142_FORMSUBMISSION_TYPE, # form526_form4142
benefits_intake_uuid: lighthouse_service.uuid,
form_data: '{}', # we have this already in the Form526Submission.form['form4142']
user_account: form526_submission.user_account,
saved_claim: form526_submission.saved_claim
kylesoskin marked this conversation as resolved.
Show resolved Hide resolved
)
FormSubmissionAttempt.create(form_submission:)
log_info[:form_submission_id] = form_submission.id
end
Rails.logger.info('Successful Form4142 Submission to Lighthouse', log_info)
kylesoskin marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always thought it was presumptive to have this log statement positioned before the upload_doc call.

end

def generate_metadata
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# frozen_string_literal: true

require 'va_notify/service'
require 'zero_silent_failures/monitor'

module EVSS
module DisabilityCompensationForm
class Form4142DocumentUploadFailureEmail < Job
STATSD_METRIC_PREFIX = 'api.form_526.veteran_notifications.form4142_upload_failure_email'
ZSF_DD_TAG_FUNCTION = 'Form 526 Flow - Form 4142 failure email sending'

# retry for one day
sidekiq_options retry: 14
Expand All @@ -17,6 +19,13 @@ class Form4142DocumentUploadFailureEmail < Job
timestamp = Time.now.utc
form526_submission_id = msg['args'].first

log_info = { job_id:, timestamp:, form526_submission_id:, error_class:, error_message: }

Rails.logger.warn(
'Form4142DocumentUploadFailureEmail retries exhausted',
log_info
)

# Job status records are upserted in the JobTracker module
# when the retryable_error_handler is called
form_job_status = Form526JobStatus.find_by(job_id:)
Expand All @@ -28,23 +37,11 @@ class Form4142DocumentUploadFailureEmail < Job
form526_submission_id:
}
}

form_job_status.update(
status: Form526JobStatus::STATUS[:exhausted],
bgjob_errors: bgjob_errors.merge(new_error)
)

Rails.logger.warn(
'Form4142DocumentUploadFailureEmail retries exhausted',
{
job_id:,
timestamp:,
form526_submission_id:,
error_class:,
error_message:
}
)

StatsD.increment("#{STATSD_METRIC_PREFIX}.exhausted")
rescue => e
Rails.logger.error(
'Failure in Form4142DocumentUploadFailureEmail#sidekiq_retries_exhausted',
Expand All @@ -59,19 +56,33 @@ class Form4142DocumentUploadFailureEmail < Job
}
)
raise e
ensure
StatsD.increment("#{STATSD_METRIC_PREFIX}.exhausted")
cl = caller_locations.first
call_location = ZeroSilentFailures::Monitor::CallLocation.new(ZSF_DD_TAG_FUNCTION, cl.path, cl.lineno)
user_account_id = begin
Form526Submission.find(form526_submission_id).user_account_id
rescue
nil
end
ZeroSilentFailures::Monitor.new(Form526Submission::ZSF_DD_TAG_SERVICE).log_silent_failure(
log_info,
user_account_id,
call_location:
)
end

def perform(form526_submission_id)
form526_submission = Form526Submission.find(form526_submission_id)

with_tracking('Form4142DocumentUploadFailureEmail', form526_submission.saved_claim_id, form526_submission_id) do
@notify_client ||= VaNotify::Service.new(Settings.vanotify.services.benefits_disability.api_key)
notify_client = VaNotify::Service.new(Settings.vanotify.services.benefits_disability.api_key)

email_address = form526_submission.veteran_email_address
first_name = form526_submission.get_first_name
date_submitted = form526_submission.format_creation_time_for_mailers

@notify_client.send_email(
notify_response = notify_client.send_email(
email_address:,
template_id: mailer_template_id,
personalisation: {
Expand All @@ -80,30 +91,36 @@ def perform(form526_submission_id)
}
)

log_mailer_dispatch(form526_submission_id)
log_mailer_dispatch(form526_submission_id, notify_response)
end
rescue => e
retryable_error_handler(e)
end

private

def zsf_monitor
@zsf_monitor ||= ZeroSilentFailures::Monitor.new(Form526Submission::ZSF_DD_TAG_SERVICE)
end

def retryable_error_handler(error)
# Needed to log the error properly in the Sidekiq::Form526JobStatusTracker::JobTracker,
# which is included near the top of this job's inheritance tree in EVSS::DisabilityCompensationForm::JobStatus
super(error)
raise error
end

def log_mailer_dispatch(form526_submission_id)
Rails.logger.info(
'Form4142DocumentUploadFailureEmail notification dispatched',
{
form526_submission_id:,
timestamp: Time.now.utc
}
)
def log_mailer_dispatch(form526_submission_id, email_response = {})
log_info = { form526_submission_id:, timestamp: Time.now.utc }
Rails.logger.info('Form4142DocumentUploadFailureEmail notification dispatched', log_info)

cl = caller_locations.first
call_location = ZeroSilentFailures::Monitor::CallLocation.new(ZSF_DD_TAG_FUNCTION, cl.path, cl.lineno)
zsf_monitor.log_silent_failure_avoided(
log_info.merge(email_confirmation_id: email_response&.id),
Form526Submission.find(form526_submission_id).user_account_id,
call_location:
)
StatsD.increment("#{STATSD_METRIC_PREFIX}.success")
end

Expand Down
8 changes: 8 additions & 0 deletions config/features.yml
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,14 @@ features:
actor_type: user
description: Manage dependent removal from view dependent page
enable_in_development: true
disability_526_form4142_polling_records:
actor_type: user
description: enables creation of, and tracking of, sent form 4142 documents, from the 526 flow, to the Lighthouse Benefits Intake API
enable_in_development: true
disability_526_form4142_polling_record_failure_email:
actor_type: user
description: enables failure email when explicit failure is detected downstream
enable_in_development: true
contention_classification_claim_linker:
actor_type: user
description: enables sending 526 claim id and vbms submitted claim id to Contention Classification service for linking/monitoring.
Expand Down
2 changes: 1 addition & 1 deletion spec/factories/users.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
verified_at { nil }
sec_id { '123498767' }
participant_id { Faker::Number.number(digits: 8) }
birls_id { Faker::Number.number(digits: 10) }
birls_id { Faker::Number.number(digits: 9) }
icn { '123498767V234859' }
kylesoskin marked this conversation as resolved.
Show resolved Hide resolved
mhv_icn { nil }
multifactor { false }
Expand Down
46 changes: 46 additions & 0 deletions spec/models/form_submission_attempt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,52 @@

expect(SimpleFormsApi::NotificationEmail).not_to have_received(:new)
end

context 'is a form526_form4142 form' do
let(:vanotify_client) { instance_double(VaNotify::Service) }
let!(:email_klass) { EVSS::DisabilityCompensationForm::Form4142DocumentUploadFailureEmail }
let!(:form526_submission) { create(:form526_submission) }
let!(:form526_form4142_form_submission) do
create(:form_submission, saved_claim_id: form526_submission.saved_claim_id,
form_type: CentralMail::SubmitForm4142Job::FORM4142_FORMSUBMISSION_TYPE)
end
let!(:form_submission_attempt) do
FormSubmissionAttempt.create(form_submission: form526_form4142_form_submission)
end

it 'sends an 4142 error email when it is not a SimpleFormsApi form and flippers are on' do
Flipper.enable(CentralMail::SubmitForm4142Job::POLLING_FLIPPER_KEY)
Flipper.enable(CentralMail::SubmitForm4142Job::POLLED_FAILURE_EMAIL)

allow(VaNotify::Service).to receive(:new).and_return(vanotify_client)
allow(vanotify_client).to receive(:send_email).and_return(OpenStruct.new(id: 'some_id'))

with_settings(Settings.vanotify.services.benefits_disability, { api_key: 'test_service_api_key' }) do
expect do
form_submission_attempt.fail!
email_klass.drain
end.to trigger_statsd_increment("#{email_klass::STATSD_METRIC_PREFIX}.success")
.and change(Form526JobStatus, :count).by(1)

job_tracking = Form526JobStatus.last
expect(job_tracking.form526_submission_id).to eq(form526_submission.id)
expect(job_tracking.job_class).to eq(email_klass.class_name)
end
end

it 'does not send an 4142 error email when it is not a SimpleFormsApi form and flippers are off' do
Flipper.disable(CentralMail::SubmitForm4142Job::POLLING_FLIPPER_KEY)
Flipper.disable(CentralMail::SubmitForm4142Job::POLLED_FAILURE_EMAIL)

with_settings(Settings.vanotify.services.benefits_disability, { api_key: 'test_service_api_key' }) do
expect do
form_submission_attempt.fail!
email_klass.drain
end.to not_trigger_statsd_increment("#{email_klass::STATSD_METRIC_PREFIX}.success")
.and not_change(Form526JobStatus, :count)
end
end
end
end
end

Expand Down
Loading
Loading