-
Notifications
You must be signed in to change notification settings - Fork 40
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
Improvements to DQ and DR PRs #1528
base: develop
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Refs: #1379
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,14 +58,17 @@ export class PatientLoaderMetriportAPI implements PatientLoader { | |
lastNameInitial: data?.lastNameInitial, | ||
}, | ||
}); | ||
// call convertToDomainObject(response) here | ||
if (!response.data) { | ||
console.log(`No patients found for ${JSON.stringify(data)}`); | ||
throw new Error(); | ||
} | ||
const patients: Patient[] = response.data.map((patient: PatientDTO) => | ||
getDomainFromDTO(patient) | ||
); | ||
patients.forEach(validatePatient); | ||
return patients; | ||
} catch (error) { | ||
console.log("Failing on request to internal endpoint", error); | ||
console.log(`Failing on request to internal endpoint ${JSON.stringify(error)}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no multiline errors |
||
throw error; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -174,6 +174,8 @@ async function createAndUploadMetadataFile({ | |
title, | ||
}); | ||
|
||
console.log(`Uploading metadata to S3 with key: ${s3MetadataFileName}`); | ||
console.log( | ||
`Uploading metadata to S3 with key: ${s3MetadataFileName}, cxId: ${cxId}, patientId: ${patientId}` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. more descriptive logging |
||
); | ||
await s3Utils.uploadFile(destinationBucket, s3MetadataFileName, Buffer.from(extrinsicObjectXml)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,13 +3,7 @@ import { | |
DocumentQueryRespToExternalGW, | ||
} from "@metriport/ihe-gateway-sdk"; | ||
import { validateDQ } from "./validating-dq"; | ||
import { | ||
XDSUnknownPatientId, | ||
XDSUnknownCommunity, | ||
XDSMissingHomeCommunityId, | ||
XDSRegistryError, | ||
constructDQErrorResponse, | ||
} from "../error"; | ||
import { IHEGatewayError, XDSRegistryError, constructDQErrorResponse } from "../error"; | ||
|
||
export async function processIncomingRequest( | ||
payload: DocumentQueryReqFromExternalGW | ||
|
@@ -28,12 +22,7 @@ export async function processIncomingRequest( | |
|
||
return response; | ||
} catch (error) { | ||
if ( | ||
error instanceof XDSUnknownPatientId || | ||
error instanceof XDSUnknownCommunity || | ||
error instanceof XDSMissingHomeCommunityId || | ||
error instanceof XDSRegistryError | ||
) { | ||
if (error instanceof IHEGatewayError) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. simplification since XDSUnknownPatientId etc are all instances of IHEGatewayError |
||
return constructDQErrorResponse(payload, error); | ||
} else { | ||
return constructDQErrorResponse(payload, new XDSRegistryError()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,15 +2,15 @@ import { | |
DocumentRetrievalReqFromExternalGW, | ||
DocumentRetrievalRespToExternalGW, | ||
} from "@metriport/ihe-gateway-sdk"; | ||
import { validateDR } from "./validating-dr"; | ||
import { validateDRAndRetrievePresignedUrls } from "./validating-dr"; | ||
import { IHEGatewayError, constructDRErrorResponse, XDSRegistryError } from "../error"; | ||
|
||
export async function processIncomingRequest( | ||
payload: DocumentRetrievalReqFromExternalGW | ||
): Promise<DocumentRetrievalRespToExternalGW> { | ||
try { | ||
// validate incoming request + look for patient and get all their documents from s3 | ||
const documents = await validateDR(payload); | ||
const documents = await validateDRAndRetrievePresignedUrls(payload); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. more descriptive function name |
||
|
||
// construct response | ||
const response: DocumentRetrievalRespToExternalGW = { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ import { XDSRegistryError } from "../error"; | |
const region = Config.getAWSRegion(); | ||
const medicalDocumentsBucketName = Config.getMedicalDocumentsBucketName(); | ||
|
||
export async function validateDR( | ||
export async function validateDRAndRetrievePresignedUrls( | ||
payload: DocumentRetrievalReqFromExternalGW | ||
): Promise<DocumentReference[]> { | ||
validateBasePayload(payload); | ||
|
@@ -27,21 +27,26 @@ export async function validateDR( | |
|
||
async function retrievePreSignedUrls(documentIds: string[]): Promise<DocumentReference[]> { | ||
const s3Utils = new S3Utils(region); | ||
const documentReferences: DocumentReference[] = []; | ||
|
||
for (const id of documentIds) { | ||
const url = await s3Utils.getSignedUrl({ | ||
bucketName: medicalDocumentsBucketName, | ||
fileName: id, | ||
}); | ||
const documentReference: DocumentReference = { | ||
homeCommunityId: METRIPORT_HOME_COMMUNITY_ID, | ||
repositoryUniqueId: METRIPORT_REPOSITORY_UNIQUE_ID, | ||
docUniqueId: id, | ||
urn: url, | ||
}; | ||
documentReferences.push(documentReference); | ||
} | ||
|
||
const promises = documentIds.map(id => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. batch for efficiency |
||
s3Utils | ||
.getSignedUrl({ | ||
bucketName: medicalDocumentsBucketName, | ||
fileName: id, | ||
}) | ||
.then(url => ({ | ||
homeCommunityId: METRIPORT_HOME_COMMUNITY_ID, | ||
repositoryUniqueId: METRIPORT_REPOSITORY_UNIQUE_ID, | ||
docUniqueId: id, | ||
urn: url, | ||
})) | ||
); | ||
|
||
const results = await Promise.allSettled(promises); | ||
|
||
const documentReferences = results | ||
.filter(result => result.status === "fulfilled") | ||
.map(result => (result as PromiseFulfilledResult<DocumentReference>).value); | ||
|
||
return documentReferences; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,6 @@ import { ContactTypes, Contact } from "../../../domain/contact"; | |
import { Address } from "../../../domain/address"; | ||
import { GenderAtBirth, Patient, PersonalIdentifier, splitName } from "../../../domain/patient"; | ||
import { getIdFromSubjectId, getIdFromSubjectRef } from "../shared"; | ||
import { uuidv7 } from "../../../util/uuid-v7"; | ||
|
||
export const genderMapping: { [k in GenderAtBirth]: "female" | "male" } = { | ||
F: "female", | ||
|
@@ -20,7 +19,7 @@ export const genderMapping: { [k in GenderAtBirth]: "female" | "male" } = { | |
export const toFHIR = (patient: Pick<Patient, "id" | "data">): FHIRPatient => { | ||
return { | ||
resourceType: "Patient", | ||
id: uuidv7(), | ||
id: patient.id, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the culprit 😭 |
||
identifier: patient.data.personalIdentifiers | ||
? convertDriversLicenseToIdentifier(patient.data.personalIdentifiers) | ||
: [], | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,8 @@ export const documentQueryReqToExternalGWSchema = documentQueryDefaultReqSchema. | |
export type DocumentQueryReqToExternalGW = z.infer<typeof documentQueryReqToExternalGWSchema>; | ||
|
||
// FROM EXTERNAL GATEWAY | ||
export const documentQueryReqFromExternalGWSchema = documentQueryDefaultReqSchema; | ||
export const documentQueryReqFromExternalGWSchema = documentQueryDefaultReqSchema.omit({ | ||
cxId: true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. omit cxId in this schema since incoming requests don't have cxId |
||
}); | ||
|
||
export type DocumentQueryReqFromExternalGW = z.infer<typeof documentQueryReqFromExternalGWSchema>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ export const SamlAttributesSchema = z.object({ | |
|
||
export const baseRequestSchema = z.object({ | ||
id: z.string(), | ||
cxId: z.string().optional(), | ||
cxId: z.string(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reverting this back to mandatory and modifying the incoming request types to omit cxId |
||
timestamp: z.string(), | ||
samlAttributes: SamlAttributesSchema, | ||
patientId: z.string().optional(), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,12 @@ import { processIncomingRequest as processIncomingPdRequest } from "@metriport/c | |
import { MPIMetriportAPI } from "@metriport/core/mpi/patient-mpi-metriport-api"; | ||
import { getEnvVarOrFail } from "@metriport/core/util/env-var"; | ||
|
||
/* | ||
This is a mock IHE gateway for Carequality interfaces to handle patient discovery (PD), | ||
document query (DQ), and document retrieval (DR) requests. Use it for testing logic in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. script explainer |
||
@metriport/core | ||
*/ | ||
|
||
import express, { Application, Request, Response } from "express"; | ||
|
||
const apiUrl = getEnvVarOrFail("API_URL"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
response.data is of type any so checking if undefined to prevent runtime errors