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

[BACK-2870] [BACK-3176] EHR Patient Tags #72

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

toddkazakov
Copy link
Collaborator

@toddkazakov toddkazakov commented Sep 26, 2024

  • Allow creating and associating patient tags with Redox create account orders
  • Allow creating accounts and enabling reports with a single order

@toddkazakov toddkazakov changed the title Allow creating and associating patient tags with Redox create account… [BACK-3176] EHR Patient Tags Oct 1, 2024
ewollesen
ewollesen previously approved these changes Oct 2, 2024
Copy link
Contributor

@ewollesen ewollesen left a comment

Choose a reason for hiding this comment

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

Looks good, just a few suggestions/questions. Nothing blocking.

I noticed that very few error paths are covered by tests. When the return path is return err, this doesn't bother me much, but many of them involve sending messages or other non-trivial logic. It's probably worth trying to cover a few more of them.

if err != nil {
return nil, err
}
if resp.StatusCode() != http.StatusOK {
Copy link
Contributor

Choose a reason for hiding this comment

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

I know these clients are automatically generated, but I really hate how they leak HTTP like a sieve. Sure, I don't see us using anything other than HTTP for this, but that's only a small part of why we abstract away those details. Oh well. (Not a comment on your code, just lamenting the leakiness of the client's abstraction.)

return nil
}

patient := (*match.Patients)[0]
Copy link
Contributor

Choose a reason for hiding this comment

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

Update: this probably isn't necessary, feel free to ignore.

Suggested change
patient := (*match.Patients)[0]
if len(match.Patients) < 1 {
return fmt.Errorf("no patient in match")
}
patient := (*match.Patients)[0]

Just to prevent a possible panic in prod.

TargetDevices: patient.TargetDevices,
Tags: tagIds,
}
resp, err := o.clinics.UpdatePatientWithResponse(ctx, *match.Clinic.Id, *patient.Id, update)
Copy link
Contributor

Choose a reason for hiding this comment

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

Update: this probably isn't necessary, feel free to ignore.

Suggested change
resp, err := o.clinics.UpdatePatientWithResponse(ctx, *match.Clinic.Id, *patient.Id, update)
if match.Clinic == nil {
return fmt.Errorf("no clinic found in match")
}
resp, err := o.clinics.UpdatePatientWithResponse(ctx, *match.Clinic.Id, *patient.Id, update)

Again, just to prevent possible panics in prod.

func (o *newOrderProcessor) getPatientTagCodes(match clinics.EHRMatchResponse) map[string]struct{} {
result := make(map[string]struct{})
if match.Settings.Tags.Codes != nil {
for _, code := range *match.Settings.Tags.Codes {
Copy link
Contributor

Choose a reason for hiding this comment

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

Here, like previous comments, is an unchecked pointer (Codes). This could panic. While highly unlikely, consider if it's worth a check to prevent.

...or is this all behind a HTTP request anyway that will recover from the panic I guess? Maybe my previous comments aren't really necessary either then, as I assume this being nil (at least when you expect it not to be nil) is quite rare. I don't love that, but it's probably the best solution.

I've updated my previous comments for these kinds of things under the assumption that in the rare event these were to panic, there is a recover() somewhere that would prevent the service from terminating due to nil pointer dereference.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Line 358 is if match.Settings.Tags.Codes != nil { so we are checking if Codes is nil

return nil
}

tagNames := make([]string, 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a curiosity question if you know off of the top of your head:

Does this offer any benefit vs tagNames := []string{}? I find this a little clearer, and I think they're equivalent, but every time I think I've got the semantics of make() memorized I find small new edge case. :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The IntelliJ linter flags []string{} for some reason. I don't know if there's any difference.

Comment on lines 378 to 392
if order.Order.ClinicalInfo != nil {
for _, info := range *order.Order.ClinicalInfo {
if info.Code != nil && info.Value != nil {
if _, ok := codes[*info.Code]; ok {
if separator == nil || *separator == "" {
tagNames = append(tagNames, strings.TrimSpace(*info.Value))
} else {
for _, tag := range strings.Split(*info.Value, *separator) {
tagNames = append(tagNames, strings.TrimSpace(tag))
}
}
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if order.Order.ClinicalInfo != nil {
for _, info := range *order.Order.ClinicalInfo {
if info.Code != nil && info.Value != nil {
if _, ok := codes[*info.Code]; ok {
if separator == nil || *separator == "" {
tagNames = append(tagNames, strings.TrimSpace(*info.Value))
} else {
for _, tag := range strings.Split(*info.Value, *separator) {
tagNames = append(tagNames, strings.TrimSpace(tag))
}
}
}
}
}
}
if *order.Order.ClinicalInfo == nil {
return nil
}
for _, info := range *order.Order.ClinicalInfo {
if info.Code == nil || info.Value == nil {
continue
}
if _, found := codes[*info.Code]; !found {
continue
}
if separator == nil || *separator == "" {
tagNames = append(tagNames, strings.TrimSpace(*info.Value))
continue
}
for _, tag := range strings.Split(*info.Value, *separator) {
tagNames = append(tagNames, strings.TrimSpace(tag))
}
}

Just a suggestion. I find it a bit easier to read, as it doesn't indent as much, and I feel like I don't have to keep as much in my head at once.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the suggestion, definitely more reasble.

@@ -81,48 +81,57 @@ func NewNewOrderProcessor(clinics clinics.ClientWithResponsesInterface, redox Cl
}

func (o *newOrderProcessor) ProcessOrder(ctx context.Context, envelope models.MessageEnvelope, order models.NewOrder) error {
match, err := o.matchOrder(ctx, envelope.Id.Hex(), order)
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the extraction of matchOrder here, feels good. 👍🏻

@toddkazakov toddkazakov changed the title [BACK-3176] EHR Patient Tags [BACK-2870] [BACK-3176] EHR Patient Tags Oct 25, 2024
@toddkazakov
Copy link
Collaborator Author

/deploy qa2

@tidebot
Copy link

tidebot commented Oct 25, 2024

toddkazakov updated values.yaml file in qa2

@tidebot
Copy link

tidebot commented Oct 25, 2024

toddkazakov updated flux policies file in qa2

@tidebot
Copy link

tidebot commented Oct 25, 2024

toddkazakov deployed clinic-worker tk-order-patient-tags branch to qa2 namespace

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.

3 participants