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

Clinical id service integration #1176

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from

Conversation

UmmulkiramR
Copy link
Contributor

Donor Repository methods have been modified to fetch the entity ids from the ID service before saving the donor in the collection.
ID generator is the one making the calls to the ID service.

async updateAll(donors: Donor[]) {
console.log('donors array in updateAll2: ' + donors[0].submitterId);
const newDonors = donors.map(async (donor) => {
// await someFunction();
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused commented code to remove

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done. removed.

),
);

return result; // newDonors.map((donor) => donor.then((d) => { return F(MongooseUtils.toPojo(d) as Donor);}).then(res => res));
Copy link
Contributor

Choose a reason for hiding this comment

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

Here as well


try {
const response = await axios.get(
// `http://localhost:9001/${req.programId}/${req.submitterId}/${req.submitterDonorId}/${req.testInterval}/${req.family_relative_id}/${req.comorbidityTypeCode}/${req.entityType}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused

@@ -123,11 +123,13 @@ const scopeCheckGenerator = (
scopesGenerator(programId),
request,
response,
);
if (unauthorizedResponse !== undefined) {
); // REMOVE THIS
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems pretty clear what to do here 😄

unsetIsNewFlagForUpdate(newDonor);

console.log('newDonor._id' + newDonor._id);
Copy link
Contributor

Choose a reason for hiding this comment

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

There are a lot of console.logs added and I'm not sure which are intentional and which are left over from testing

It would be good to replace those you want to keep with the L logger used elsewhere in the app; do a search for const L or L.info for examples

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed all console logs.

entityType: 'null',
};

export interface PartialDonor {
Copy link
Contributor

Choose a reason for hiding this comment

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

This basically duplicates type Donor, could we achieve the same thing doing interface PartialDonor extends Partial<Donor> {} or something similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that's a good idea. Thanks.

entityType: ClinicalEntitySchemaNames.DONOR,
});
donor.donorId = donorId;
console.log(donor.donorId);
Copy link
Contributor

@demariadaniel demariadaniel Apr 15, 2024

Choose a reason for hiding this comment

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

This should print more than just a number, it needs context, at the very least: donor.donorId: ${donor.donorId} similar to the other logs in this function

@@ -313,7 +313,7 @@ class SubmissionController {

// GQL Query Methods
async commitActiveSubmissionData(programId: string, egoToken: string, versionId: string) {
queryHasProgramWriteAccess(programId, egoToken);
// queryHasProgramWriteAccess(programId, egoToken); // REMOVE THIS
Copy link
Contributor

Choose a reason for hiding this comment

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

As well ^

config.getConfig().tokenUrl() +
`${req.programId}/${req.submitterId}/${req.submitterDonorId}/${req.testInterval}/${req.family_relative_id}/${req.comorbidityTypeCode}/${req.entityType}`,
headers,
);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would typically define this url in a variable which is then passed to axios.get rather than putting logic in the function arguments

const url = `${config.getConfig().tokenUrl()}/${req.programId}/${req.submitterId}/${req.submitterDonorId}/${req.testInterval}/${req.family_relative_id}/${req.comorbidityTypeCode}/${req.entityType}`;

const response = await axios.get(url, headers);

Also note I added a trailing slash between tokenUrl and the string of paths req.programId/ etc ... if youre defining the tokenUrl with a slash then this is not needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done. Thanks.

`${req.programId}/${req.submitterId}/${req.submitterDonorId}/${req.testInterval}/${req.family_relative_id}/${req.comorbidityTypeCode}/${req.entityType}`,
headers,
);
console.log('getId response: ' + response.data.entityId + ' - ' + response.data.entityType);
Copy link
Contributor

Choose a reason for hiding this comment

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

Just FYI string concatenation like this is generally out of favour compared to template literals

`getId response: ${response.data.entityId} - ${response.data.entityType}`

String + value (concatenation) can sometimes have unexpected results when parsing a value that is not originally a string
Template literals are also slightly cleaner to read + write

Copy link
Contributor Author

Choose a reason for hiding this comment

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

have removed all unwanted console logs

Copy link
Member

Choose a reason for hiding this comment

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

Dan's suggestion, for clarity

Suggested change
console.log('getId response: ' + response.data.entityId + ' - ' + response.data.entityType);
console.log(`getId response: ${response.data.entityId} - ${response.data.entityType}`);

submitterDonorId: bm.clinicalInfo.submitter_donor_id as string,
testInterval: bm.clinicalInfo.test_interval as string,
entityType: ClinicalEntitySchemaNames.BIOMARKER,
});
Copy link
Contributor

@demariadaniel demariadaniel Apr 15, 2024

Choose a reason for hiding this comment

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

When grabbing many values from the same object you can use destructuring variable assignment to simplify things:

			const {
				submitter_donor_id,
				submitter_specimen_id,
				submitter_primary_diagnosis_id,
				submitter_follow_up_id,
				submitter_treatment_id,
				test_interval,
			} = bm.clinicalInfo;

			const submitterBiomarkerId =
				submitter_specimen_id?.toString() ??
				submitter_primary_diagnosis_id?.toString() ??
				submitter_follow_up_id?.toString() ??
				submitter_treatment_id?.toString() ??
				'null';

			const id = await getId({
				...request,
				programId: donor.programId as string,
				submitterId: submitterBiomarkerId,
				submitterDonorId: submitter_donor_id as string,
				testInterval: test_interval as string,
				entityType: ClinicalEntitySchemaNames.BIOMARKER,
			});

Copy link
Contributor

Choose a reason for hiding this comment

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

Also generally prefer descriptive variable names -- biomarker vs bm

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed bm to biomarker and for all other entities. But I'd prefer not to use the destructured variable assignment here for now

Copy link
Contributor

@demariadaniel demariadaniel left a comment

Choose a reason for hiding this comment

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

Functionality looks good but there's some clean up to do and some style recommendations before merging

@ciaranschutte
Copy link
Contributor

@demariadaniel @UmmulkiramR

!!'null' // true
!!null // false

}

const request = {
programId: 'null',
Copy link
Member

Choose a reason for hiding this comment

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

As discussed over zoom, this was made as a conscious choice, WIP in the context of query params in http requests, geared towards representing the difference between empty values for a param (null), vs missing parameters altogether (undefined). Will be addressed in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

have replaced the the null with a '-'

}

export async function setEntityIds(donor: PartialDonor) {
const submitterDonorId = donor.submitterId as string;
Copy link
Contributor

Choose a reason for hiding this comment

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

One more thing I want to take a look at, I think we can update PartialDonor like this:

export interface PartialDonor extends Partial<Donor> {
	submitterId: string;
	programId: string;
}

and then you can remove repeated use of as string in this function and elsewhere. These two keys are typically required keys in Donor so I think it fits your usage.

We try to avoid using as because it can create situations where you're misleading Typescript. For example, donor.submitterId could actually be undefined and TS wouldn't know.

Tagging @justincorrigible (may want to ask Jon?) because as usage is something we've discussed frequently before so thought I'd get a second opinion

@UmmulkiramR UmmulkiramR linked an issue May 15, 2024 that may be closed by this pull request
UmmulkiramR added 4 commits June 11, 2024 10:25
* develop:
  fix to resolve incorrect merging of therapies into treatments (#1187)
  Chore / Move Clinical Service Types (#1185)
  ❌ Sort Invalid Clinical Records first (#1184)
  RC 1.87.1
  Remove unused argument (#1179)
  🏷️ 1141 Add Exception Manifest to Donor tsv (#1178)
  Fixed Resolver (#1177)
  Add Exceptions to Program TSV (#1175)
Copy link
Member

@joneubank joneubank left a comment

Choose a reason for hiding this comment

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

Generally workable solution. The ID path is shockingly long and I am wondering if this is a configuration/design concern with the ID service instead of a problem with the implementation here.

My only feedback for changes is to listen to the TS errors and perform required type checks instead of just asserting new types. TS can't provide us any meaningful protection against invalid types if we keep telling it that it is wrong.

src/clinical/id-generator.ts Outdated Show resolved Hide resolved
Comment on lines +69 to +71
const url =
config.getConfig().idServiceUrl() +
`${req.programId}/${req.submitterDonorId}/${req.submitterSpecimenId}/${req.submitterSampleId}/${req.submitterPrimaryDiagnosisId}/${req.submitterFollowUpId}/${req.submitterTreatmentId}/${req.testInterval}/${req.family_relative_id}/${req.comorbidityTypeCode}/${req.entityType}`;
Copy link
Member

Choose a reason for hiding this comment

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

Strongly encourage the use of URL building libraries for this specific purpose: https://www.npmjs.com/package/url-join

See also the JS URL constructor: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL

src/clinical/id-generator.ts Show resolved Hide resolved
Comment on lines 28 to 54
interface IdGenerationRequest {
programId: string;
submitterSpecimenId: string;
submitterSampleId: string;
submitterPrimaryDiagnosisId: string;
submitterFollowUpId: string;
submitterTreatmentId: string;
submitterDonorId: string;
testInterval: string;
family_relative_id: string;
comorbidityTypeCode: string;
entityType: string;
}

const request = {
programId: '-',
submitterSpecimenId: '-',
submitterSampleId: '-',
submitterPrimaryDiagnosisId: '-',
submitterFollowUpId: '-',
submitterTreatmentId: '-',
submitterDonorId: '-',
testInterval: '-',
family_relative_id: '-',
comorbidityTypeCode: '-',
entityType: '-',
};
Copy link
Member

Choose a reason for hiding this comment

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

Probably just want to use a Partial version of this object and then let the consuming function convert the undefined values to whatever palceholder string we want. This is simpler than requiring the user submitting the request to understand that '-' is a placeholder value.

src/clinical/id-generator.ts Outdated Show resolved Hide resolved
const submitterDonorId = donor.submitterId as string;
// -- DONOR --
const donorId = await getId({
...request,
Copy link
Member

Choose a reason for hiding this comment

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

This relates to my previous comment about using a Partial type for input. You can do this ...request filling inside of the getId function so that we don't need to remember to do this when calling the function.

src/clinical/id-generator.ts Outdated Show resolved Hide resolved
src/utils.ts Outdated Show resolved Hide resolved
Comment on lines 119 to +125
export const donorDao: DonorRepository = {
async insertDonors(donors: Donor[]) {
await mongoose.connection.db.collection('donors').insertMany(donors);
const donorsWithIds = await setEntityIdsForDonors(donors);
await mongoose.connection.db.collection('donors').insertMany(donorsWithIds);
},
async updateDonor(donor: Donor) {
const donorsWithIds = await setEntityIds(donor);
Copy link
Member

Choose a reason for hiding this comment

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

Both setEntityIds functions throw errors when network errors occur, should there be some sort of error handling here to handle failures or is this now expected to be handled by the caller of updateDonor and insertDonors?

Co-authored-by: Anders Richardsson <[email protected]>
@joneubank joneubank self-requested a review August 12, 2024 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Integrate ID generation with the Clinical Service.
5 participants