Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
159 changes: 82 additions & 77 deletions app/jobs/get_usps_proofing_results_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,6 @@ class GetUspsProofingResultsJob < ApplicationJob

queue_as :long_running

def email_analytics_attributes(enrollment)
{
timestamp: Time.zone.now,
user_id: enrollment.user_id,
service_provider: enrollment.issuer,
wait_until: mail_delivery_params(enrollment.proofed_at)[:wait_until],
}
end

def enrollment_analytics_attributes(enrollment, complete:)
{
enrollment_code: enrollment.enrollment_code,
enrollment_id: enrollment.id,
minutes_since_last_status_check: enrollment.minutes_since_last_status_check,
minutes_since_last_status_update: enrollment.minutes_since_last_status_update,
minutes_since_established: enrollment.minutes_since_established,
minutes_to_completion: complete ? enrollment.minutes_since_established : nil,
issuer: enrollment.issuer,
}
end

def response_analytics_attributes(response)
return { response_present: false } unless response.present?

{
fraud_suspected: response['fraudSuspected'],
primary_id_type: response['primaryIdType'],
secondary_id_type: response['secondaryIdType'],
failure_reason: response['failureReason'],
transaction_end_date_time: parse_usps_timestamp(response['transactionEndDateTime']),
transaction_start_date_time: parse_usps_timestamp(response['transactionStartDateTime']),
status: response['status'],
assurance_level: response['assuranceLevel'],
proofing_post_office: response['proofingPostOffice'],
proofing_city: response['proofingCity'],
proofing_state: response['proofingState'],
scan_count: response['scanCount'],
response_message: response['responseMessage'],
response_present: true,
}
end

def perform(_now)
return true unless IdentityConfig.store.in_person_proofing_enabled

Expand All @@ -66,6 +24,7 @@ def perform(_now)
enrollments_in_progress: 0,
enrollments_passed: 0,
}

reprocess_delay_minutes = IdentityConfig.store.
get_usps_proofing_results_job_reprocess_delay_minutes
enrollments = InPersonEnrollment.needs_usps_status_check(
Expand Down Expand Up @@ -93,53 +52,99 @@ def perform(_now)
attr_accessor :enrollment_outcomes

DEFAULT_EMAIL_DELAY_IN_HOURS = 1
REQUEST_DELAY_IN_SECONDS = IdentityConfig.store.
get_usps_proofing_results_job_request_delay_milliseconds / MILLISECONDS_PER_SECOND

def check_enrollments(enrollments)
request_delay_in_seconds = IdentityConfig.store.
get_usps_proofing_results_job_request_delay_milliseconds / MILLISECONDS_PER_SECOND
proofer = UspsInPersonProofing::Proofer.new
def proofer
@proofer ||= UspsInPersonProofing::Proofer.new
Copy link
Contributor

Choose a reason for hiding this comment

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

The ||= syntax is a favorite of mine.

end

def check_enrollments(enrollments)
last_enrollment_index = enrollments.length - 1
enrollments.each_with_index do |enrollment, idx|
# Add a unique ID for enrollments that don't have one
enrollment.update(unique_id: enrollment.usps_unique_id) if enrollment.unique_id.blank?
check_enrollment(enrollment)
# Sleep briefly after each call to USPS
sleep REQUEST_DELAY_IN_SECONDS if idx < last_enrollment_index
end
end

status_check_attempted_at = Time.zone.now
enrollment_outcomes[:enrollments_checked] += 1
response = nil
def check_enrollment(enrollment)
# Add a unique ID for enrollments that don't have one
enrollment.update(unique_id: enrollment.usps_unique_id) if enrollment.unique_id.blank?

begin
response = proofer.request_proofing_results(
enrollment.unique_id, enrollment.enrollment_code
)
rescue Faraday::BadRequestError => err
# 400 status code. This is used for some status updates and some common client errors
handle_bad_request_error(err, enrollment)
rescue Faraday::ClientError, Faraday::ServerError => err
# 4xx or 5xx status code. These are unexpected but will have some sort of
# response body that we can try to log data from
handle_client_or_server_error(err, enrollment)
rescue Faraday::Error => err
# Timeouts, failed connections, parsing errors, and other HTTP errors. These
# generally won't have a response body
handle_faraday_error(err, enrollment)
rescue StandardError => err
handle_standard_error(err, enrollment)
else
process_enrollment_response(enrollment, response)
ensure
# Record the attempt to update the enrollment
enrollment.update(status_check_attempted_at: status_check_attempted_at)
end
status_check_attempted_at = Time.zone.now
enrollment_outcomes[:enrollments_checked] += 1
response = nil

# Sleep for a while before we attempt to make another call to USPS
sleep request_delay_in_seconds if idx < enrollments.length - 1
end
response = proofer.request_proofing_results(
enrollment.unique_id, enrollment.enrollment_code
)
rescue Faraday::BadRequestError => err
# 400 status code. This is used for some status updates and some common client errors
handle_bad_request_error(err, enrollment)
rescue Faraday::ClientError, Faraday::ServerError => err
# 4xx or 5xx status code. These are unexpected but will have some sort of
# response body that we can try to log data from
handle_client_or_server_error(err, enrollment)
rescue Faraday::Error => err
# Timeouts, failed connections, parsing errors, and other HTTP errors. These
# generally won't have a response body
handle_faraday_error(err, enrollment)
rescue StandardError => err
handle_standard_error(err, enrollment)
else
process_enrollment_response(enrollment, response)
ensure
# Record the attempt to update the enrollment
enrollment.update(status_check_attempted_at: status_check_attempted_at)
end

def analytics(user: AnonymousUser.new)
Analytics.new(user: user, request: nil, session: {}, sp: nil)
end

def email_analytics_attributes(enrollment)
{
timestamp: Time.zone.now,
user_id: enrollment.user_id,
service_provider: enrollment.issuer,
wait_until: mail_delivery_params(enrollment.proofed_at)[:wait_until],
}
end

def enrollment_analytics_attributes(enrollment, complete:)
{
enrollment_code: enrollment.enrollment_code,
enrollment_id: enrollment.id,
minutes_since_last_status_check: enrollment.minutes_since_last_status_check,
minutes_since_last_status_update: enrollment.minutes_since_last_status_update,
minutes_since_established: enrollment.minutes_since_established,
minutes_to_completion: complete ? enrollment.minutes_since_established : nil,
issuer: enrollment.issuer,
}
end

def response_analytics_attributes(response)
return { response_present: false } unless response.present?

{
fraud_suspected: response['fraudSuspected'],
primary_id_type: response['primaryIdType'],
secondary_id_type: response['secondaryIdType'],
failure_reason: response['failureReason'],
transaction_end_date_time: parse_usps_timestamp(response['transactionEndDateTime']),
transaction_start_date_time: parse_usps_timestamp(response['transactionStartDateTime']),
status: response['status'],
assurance_level: response['assuranceLevel'],
proofing_post_office: response['proofingPostOffice'],
proofing_city: response['proofingCity'],
proofing_state: response['proofingState'],
scan_count: response['scanCount'],
response_message: response['responseMessage'],
response_present: true,
}
end

def handle_bad_request_error(err, enrollment)
response_body = err.response_body
response_message = response_body&.[]('responseMessage')
Expand Down
7 changes: 4 additions & 3 deletions spec/jobs/get_usps_proofing_results_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,10 @@
allow(job).to receive(:analytics).and_return(job_analytics)
allow(IdentityConfig.store).to receive(:get_usps_proofing_results_job_reprocess_delay_minutes).
and_return(reprocess_delay_minutes)
allow(IdentityConfig.store).
to receive(:get_usps_proofing_results_job_request_delay_milliseconds).
and_return(request_delay_ms)
stub_const(
'GetUspsProofingResultsJob::REQUEST_DELAY_IN_SECONDS',
request_delay_ms / GetUspsProofingResultsJob::MILLISECONDS_PER_SECOND,
)
stub_request_token
if respond_to?(:pending_enrollment)
pending_enrollment.update(enrollment_established_at: 3.days.ago)
Expand Down