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

feat(#9194): add api support for getting place by uuid #9177

Merged
merged 83 commits into from
Jul 1, 2024
Merged

Conversation

jkuester
Copy link
Contributor

@jkuester jkuester commented Jun 12, 2024

Description

Closes #9194

Docs PR: medic/cht-docs#1423

This PR adds support for get-place and get-place-with-lineage workflows in both cht-datasource and api REST endpoint.

Additionally, I have "refactored" some code throughout the codebase to use the cht-datasource functionality. My goal here was not to update every possible instance, but to try and snag all of the easy/simple cases where we are getting a person/place. The only places I ended up adding additional logic/tests for this re-factoring was when it made sense to throw an error if the person/place was not found (the previous PouchDB.get code had this behavior, but often we seem to have relied on it without testing it).

When deciding what code I could refactor to use the new APIs, the main consideration was how confident we could be that we knew specifically in that code that the contact we were getting was a person or a place (in many cases we just retrieve a generic contact and do not know what it is until the doc comes back. See #9065 (comment) for more discussion of this challenge.) When deciding a particular piece of code could be refactored, I weighed it against these considerations:

  • By the context, we could be sure of the type of contact we are getting. (E.g.: This was the case in some of the shared-lib/contacts logic where it was clear from the function names and surround logic, exactly what we were trying to do.)
  • I assumed that the contact associated with a user should always be a person and the facility should always be a place
  • I assumed that the parent for any contact should always be a place

If any of these assumptions seems like too much of a stretch or some code change feels risky. call it out! I think for this PR, it would be better to just roll back the change and move on for now than get caught up too deep in logic/refactoring investigations....

Related code changes:

Code review checklist

  • Readable: Concise, well named, follows the style guide, documented if necessary.
  • Documented: Configuration and user documentation on cht-docs
  • Tested: Unit and/or e2e where appropriate
  • Internationalised: All user facing text
  • Backwards compatible: Works with existing data and configuration or includes a migration. Any breaking changes documented in the release notes.

Compose URLs

If Build CI hasn't passed, these may 404:

License

The software is provided under AGPL-3.0. Contributions to this project are accepted under the same license.

jkuester added 30 commits May 2, 2024 15:33
# Conflicts:
#	sentinel/src/lib/purging.js
Switched back to fetch api for now.  Also made url optional for remote datasoure (allowing for relative requests from webapp/admin).
Base automatically changed from 9065_get_person_with_lineage to master June 14, 2024 21:20
@@ -17,7 +16,7 @@ export namespace v1 {
return false;
}
const hasPersonType = contactTypeUtils.isPerson(settings.getAll(), doc);
if (!hasPersonType || !isNormalizedParent(doc)) {
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 got too scared of this isNormalizedParent check since it is validating the contents of parent. I don't think, especially in v1, we want to block reading a contact because of problems in their parent lineage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, it is worth noting that the original logic when reading a person in shared-libs/contacts was just to check the type and nothing else. So we are staying consistent here and avoiding new validations.

@jkuester jkuester requested review from m5r and lorerod June 18, 2024 22:08
@jkuester
Copy link
Contributor Author

@lorerod I was hoping you could just give a quick review of this PR since it is so close in functionality to the get-person and get-person-with-lineage PRs you reviewed recently! 🙏 (There are a lot of other file changes, but the only behavior change is the addition of the get-place REST endpoint. That is why that is the only integration/e2e test change. Everything else should be passive.)

@jkuester jkuester marked this pull request as ready for review June 18, 2024 22:10
Copy link
Contributor

@lorerod lorerod left a comment

Choose a reason for hiding this comment

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

@jkuester, thank you for this feature, the refactoring, and the thorough testing. I left a comment inline, but it's not a blocker.

Comment on lines +43 to +44
const getPlace = Place.v1.get(dataContext);
const getPlaceWithLineage = Place.v1.getWithLineage(dataContext);
Copy link
Contributor

Choose a reason for hiding this comment

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

What would happen if the dataContext is invalid? Do you think this could happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In general, if you try to curry in an invalid dataContext (e.g. null, or some other value), this line will throw an exception.

However, in this case, dataContext cannot be invalid here. The call above on L30 to getRemoteDataContext will either return a valid data context or it will throw an exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a number of unit tests for these error scenarios in cht-datasource, but I did not think it was worth adding any integration tests since the validation logic all happens in cht-datasource and so there is not really anything to "integrate" with in those test cases.

A separate kind of test would be to create a remote data context with an invalid URL (one that does not actually point to a CHT instance). In that case, we would not fail until below when we call the getPlaceWithLineage function and that will throw an HTTP error (maybe a timeout error trying to connect to a server that does not exist??) We don't have any test like that yet, (and probably does not belong in the place controller tests), but maybe we should consider some more generic cht-datasource integration tests... 🤔 Let me know if you want to see that as a part of this PR!

@jkuester jkuester changed the title feat(#9065): add api support for getting place by uuid feat(#9194): add api support for getting place by uuid Jun 21, 2024
Copy link
Member

@m5r m5r left a comment

Choose a reason for hiding this comment

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

@sugat009 I've reviewed Josh's changes and made additional changes to get the CI to pass, could you take a look at it?

@@ -0,0 +1,5 @@
module.exports = {
init: function(dataContext) {
Object.assign(module.exports, dataContext, { init: this.init });
Copy link
Member

Choose a reason for hiding this comment

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

I'm not a fan of this pattern because it's a bit obscure, it's not immediately clear what it does.
I have yet to come up with a clearer alternative. The first thing I thought of involved using a global variable to store dataContext but it's a worse approach imo as it would conflict with other instances of dataContext spawned within the same process but for different purposes...

I see this pattern is used in 10 different places in the code base already so let's keep it this way for now and revisit later. I suspect it won't be problematic until we want to switch to typescript

Copy link
Contributor Author

Choose a reason for hiding this comment

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

100% agree. This is basically just a janky hacked-up form of dependency injection. However, as you noted, any alternative approach seems way worse. At lease until we come up with a more proper DI solution, it seems like this weirdness gives us the best balance of testing flexibility while localizing most of the weirdness to just these files.

@m5r m5r requested a review from sugat009 June 27, 2024 00:05
@m5r m5r merged commit 282faee into master Jul 1, 2024
42 checks passed
@m5r m5r deleted the 9065_get_place branch July 1, 2024 13:10
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.

API Endpoint for getting place by UUID
4 participants