-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add OH allergies feature toggle * add LH specfic client and config, use param to determine path * Refactor LighthouseClient and LighthouseConfiguration - Remove unnecessary code and comments in LighthouseClient - Update base_path method in LighthouseClient to use the base URL from settings - Clean up imports and remove unused middleware in LighthouseConfiguration - Update token_request_url and client_id methods in LighthouseConfiguration to use values from settings - Update key method in LighthouseConfiguration to use the private key from settings - Update build method in LighthouseConfiguration to use the launch method for encoding the ICN - Update lighthouse_headers method in LighthouseConfiguration to use symbol syntax for headers - Update get_token method in LighthouseConfiguration to parse the access_token from the response body - Remove unused include and skip_before_action in MrController - Conditionally include and skip_before_action in MrController based on use_oh_data_path parameter - Update client method in MrController to conditionally instantiate LighthouseClient or Client based on use_oh_data_path parameter * Respect feature toggle * Measure LH call durations * clean up and set default count * Add betamocks config * Add betamocks config for lh patient health api * Update mock variable format to match other LH services * Update to remove assumptions around FHIR client * Fetch individual allergy resources * Update betamocks config * Remove in progress code * Restore comment * Add spec wip * Don't reinit allergies client * Working version of lh allergies test * Update lh client authenticate method * Add better comment for lighthouse_client::authenticate * Improve VH client handling * Default new feature toggle to false in dev * Add spec for show allergy (OH data path) * Remove logging * Update lib/medical_records/lighthouse_client.rb * Initialize lh client in class method --------- Co-authored-by: Stephen Barrs <stephen.barrs@va.gov>
- Loading branch information
1 parent
2ec7ecc
commit 3e0d6f8
Showing
12 changed files
with
526 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'common/client/base' | ||
require 'lighthouse/veterans_health/client' | ||
|
||
module MedicalRecords | ||
## | ||
# Core class responsible for Medical Records API interface operations with the Lighthouse FHIR server. | ||
# | ||
class LighthouseClient < Common::Client::Base | ||
## | ||
# Initialize the client | ||
# | ||
# @param icn [String] MHV patient ICN | ||
# | ||
def initialize(icn) | ||
super() | ||
|
||
raise Common::Exceptions::ParameterMissing, 'ICN' if icn.blank? | ||
|
||
@icn = icn | ||
end | ||
|
||
def authenticate | ||
# FIXME: Explore doing this in a less janky way. | ||
# This is called by the MHV Controller Concern, but is not needed for this client | ||
# because it is handled in Lighthouse::VeteransHealth::Client::retrieve_bearer_token | ||
end | ||
|
||
def lighthouse_client | ||
@lighthouse_client ||= Lighthouse::VeteransHealth::Client.new(@icn) | ||
end | ||
|
||
def list_allergies | ||
bundle = lighthouse_client.list_allergy_intolerances | ||
bundle = Oj.load(bundle[:body].to_json, symbol_keys: true) | ||
sort_bundle(bundle, :recordedDate, :desc) | ||
end | ||
|
||
def get_allergy(allergy_id) | ||
bundle = lighthouse_client.get_allergy_intolerance(allergy_id) | ||
Oj.load(bundle[:body].to_json, symbol_keys: true) | ||
end | ||
|
||
protected | ||
|
||
def handle_api_errors(result) | ||
if result.code.present? && result.code >= 400 | ||
body = JSON.parse(result.body) | ||
diagnostics = body['issue']&.first&.fetch('diagnostics', nil) | ||
diagnostics = "Error fetching data#{": #{diagnostics}" if diagnostics}" | ||
|
||
# Special-case exception handling | ||
if result.code == 500 && diagnostics.include?('HAPI-1363') | ||
# "HAPI-1363: Either No patient or multiple patient found" | ||
raise MedicalRecords::PatientNotFound | ||
end | ||
|
||
# Default exception handling | ||
raise Common::Exceptions::BackendServiceException.new( | ||
"MEDICALRECORDS_#{result.code}", | ||
status: result.code, | ||
detail: diagnostics, | ||
source: self.class.to_s | ||
) | ||
end | ||
end | ||
|
||
## | ||
# Merge two FHIR bundles into one, with an updated total count. | ||
# | ||
# @param bundle1 [FHIR:Bundle] The first FHIR bundle | ||
# @param bundle2 [FHIR:Bundle] The second FHIR bundle | ||
# @param page_num [FHIR:Bundle] | ||
# | ||
def merge_bundles(bundle1, bundle2) | ||
unless bundle1.resourceType == 'Bundle' && bundle2.resourceType == 'Bundle' | ||
raise 'Both inputs must be FHIR Bundles' | ||
end | ||
|
||
# Clone the first bundle to avoid modifying the original | ||
merged_bundle = bundle1.clone | ||
|
||
# Merge the entries from the second bundle into the merged_bundle | ||
merged_bundle.entry ||= [] | ||
bundle2.entry&.each do |entry| | ||
merged_bundle.entry << entry | ||
end | ||
|
||
# Update the total count in the merged bundle | ||
merged_bundle.total = merged_bundle.entry.count | ||
|
||
merged_bundle | ||
end | ||
|
||
## | ||
# Apply pagination to the entries in a FHIR::Bundle object. This assumes sorting has already taken place. | ||
# | ||
# @param entries a list of FHIR objects | ||
# @param page_size [Fixnum] page size | ||
# @param page_num [Fixnum] which page to return | ||
# | ||
def paginate_bundle_entries(entries, page_size, page_num) | ||
start_index = (page_num - 1) * page_size | ||
end_index = start_index + page_size | ||
paginated_entries = entries[start_index...end_index] | ||
|
||
# Return the paginated result or an empty array if no entries | ||
paginated_entries || [] | ||
end | ||
|
||
## | ||
# Sort the FHIR::Bundle entries on a given field and sort order. If a field is not present, that entry | ||
# is sorted to the end. | ||
# | ||
# @param bundle [FHIR::Bundle] the bundle to sort | ||
# @param field [Symbol, String] the field to sort on (supports nested fields with dot notation) | ||
# @param order [Symbol] the sort order, :asc (default) or :desc | ||
# | ||
def sort_bundle(bundle, field, order = :asc) | ||
field = field.to_s | ||
sort_bundle_with_criteria(bundle, order) do |resource| | ||
fetch_nested_value(resource, field) | ||
end | ||
end | ||
|
||
## | ||
# Sort the FHIR::Bundle entries based on a provided block. The block should handle different resource types | ||
# and define how to extract the sorting value from each. | ||
# | ||
# @param bundle [FHIR::Bundle] the bundle to sort | ||
# @param order [Symbol] the sort order, :asc (default) or :desc | ||
# | ||
def sort_bundle_with_criteria(bundle, order = :asc) | ||
sorted_entries = bundle[:entry].sort do |entry1, entry2| | ||
value1 = yield(entry1[:resource]) | ||
value2 = yield(entry2[:resource]) | ||
if value2.nil? | ||
-1 | ||
elsif value1.nil? | ||
1 | ||
else | ||
order == :asc ? value1 <=> value2 : value2 <=> value1 | ||
end | ||
end | ||
bundle[:entry] = sorted_entries | ||
bundle | ||
end | ||
|
||
## | ||
# Fetches the value of a potentially nested field from a given object. | ||
# | ||
# @param object [Object] the object to fetch the value from | ||
# @param field_path [String] the dot-separated path to the field | ||
# | ||
def fetch_nested_value(object, field_path) | ||
field_path.split('.').reduce(object) do |obj, method| | ||
obj.respond_to?(method) ? obj.send(method) : nil | ||
end | ||
end | ||
|
||
def measure_duration(event: 'default', tags: []) | ||
# Use time since boot to avoid clock skew issues | ||
# https://github.com/sidekiq/sidekiq/issues/3999 | ||
start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) | ||
result = yield | ||
duration = (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start_time).round(4) | ||
|
||
StatsD.measure("api.mhv.lighthouse.#{event}.duration", duration, tags:) | ||
result | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.