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

[Location Hierarchy] Enable storing ancestor tags on all locations. #110

Open
7 tasks
dubdabasoduba opened this issue Jan 21, 2025 · 3 comments
Open
7 tasks

Comments

@dubdabasoduba
Copy link
Member

dubdabasoduba commented Jan 21, 2025

Context

  • Location hierarchies are defined by the partOf relationship in Location resources.
  • The gateway server leverages these hierarchies for several operations i.e
    • Including retrieving hierarchical data from the location hierarchy endpoint
    • Downloading resources via the Related Entity Location (REL) sync strategy.
  • However, the recursive nature of hierarchy generation imposes high computational and memory overhead on both servers and mobile clients, leading to performance bottlenecks such as slow response times or complete request failures.
  • To mitigate these issues, this proposal suggests augmenting each Location resource’s meta.tags with the IDs of all parent locations, up to the root.
    • By storing the entire lineage in meta.tags, search queries for a given location ID can be handled natively by HAPI or other SDK search libraries, removing the need for expensive custom recursion logic.
    • This approach should reduce resource consumption, improve performance, and streamline location-based queries.
  • The proposal is to have the codes look something like this
    • system - This is an OpenSRP defined system. We can change it to anything.
    • code - This is the location ID for the parent location
    • display - This can be the Location Name. We can also add the location level here e.g Level 2
{
  "system": "http://smartregister.org/CodeSystem/location-lineage",
  "code": "4ddd4157-921b-4c65-820c-161b6e845011"
}
  • This ticket will address the addition of the lineage if any every time we PUT | POST data via the FHIR location endpoint

Implementation

  • Implement a function to intercept the PUT or POST request at the location endpoint. This function would then update the Location resource with the Location's lineage.
    • On POST: When creating a new Location, derive the lineage by fetching its parent (if provided) and constructing the hierarchical path.
    • On PUT: When updating an existing Location, check if the parent or hierarchy has changed. If so, recalculate the lineage. The recalculation will follow the same approach as the POST route.
    • The above functionality should only run if the Location.partOf is not empty and references a valid location.
  • The lineage should represent the hierarchical relationship of a location, which could include parent-child relationships or other contextual data. Example: Root > Region > District > Facility>village

Acceptance Criteria

  • Each Location resource with a valid Location.partOf should have its ancestral lineage automatically linked in the Location.meta.tag property when added or updated via the API.
  • The functionality above should stop in case the location references on the Location.partOf define a cyclic dependence

Location Resource sample

{
  "resourceType": "Location",
  "id": "aa5ac053-d8aa-4f42-b326-bae32e5944e1",
  "meta": {
    "versionId": "2",
    "lastUpdated": "2024-07-22T15:13:53.014+00:00",
    "source": "#1b7d28fd21bf0b63",
    "tag": [
      {
        "system" : "http://smartregister.org/CodeSystem/location-lineage",
        "code"   : "03176924-6b3c-4b74-bccd-32afcceebabd"                  ,
      },
      {
        "system" : "http://smartregister.org/CodeSystem/location-lineage",
        "code"   : "bf116fdd-6617-4302-88e4-72fd1af2851c"                  ,
      },
      {
        "system" : "http://smartregister.org/CodeSystem/location-lineage",
        "code"   : "696b532f-15b1-4422-a0ab-3525587260cd"                  ,
      }
    ]
  },
  "identifier": [
    {"use": "official", "value": "aa5ac053-d8aa-4f42-b326-bae32e5944e1"}
  ],
  "status": "active",
  "name": "Ambandrika",
  "type": [
    {
      "coding": [
        {
          "system" : "http://terminology.hl7.org/CodeSystem/location-type",
          "code"   : "jdn"                                                ,
          "display": "jurisdiction"
        }
      ]
    },
    {
      "coding": [
        {
          "system" : "https://smartregister.org/codes/administrative-level",
          "code"   : "4"                                                   ,
          "display": "Level 4"
        }
      ]
    },
    {
      "coding": [
        {
          "system": "http://terminology.hl7.org/CodeSystem/location-physical-type",
          "code": "jdn",
          "display": "Jurisdiction"
        }
      ]
    }
  ],
  "physicalType": {
    "coding": [
      {
        "system": "http://terminology.hl7.org/CodeSystem/location-physical-type",
        "code": "jdn",
        "display": "Jurisdiction"
      }
    ]
  },
  "partOf": {
    "reference": "Location/696b532f-15b1-4422-a0ab-3525587260cd",
    "display"  : "Ambatondrazaka"
  }
}
@pld
Copy link
Member

pld commented Jan 21, 2025

A couple questions:

  • should be configurable, like a feature flag on the gateway to determine if it runs?
  • I think we should not set the display key
  • implementation POST, more specifically, this is to fetch all the parent nodes
  • implementation PUT, the condition is that if the parent has changed, like what is the way the hierarchy changes without the parent changing? The recalculation must happen for more nodes than it POST, where it only happens for the node being created. If PUT changes the parent, then you need to recalculate for the node being being posted and ALL of its descendants (ie all nodes in the subtree where the node PUT is the root), this will be expensive

@dubdabasoduba
Copy link
Member Author

Should it be configurable, like a feature flag on the gateway to determine if it runs?

I think we can make it configurable, we will need to work on onaio/fhir-tooling#328 though to ensure the tags can be added when necessary

@dubdabasoduba
Copy link
Member Author

I think we should not set the display key

I agree, removing them adds an extra look up step when trying to troubleshoot the tags addition or fetching but I think that's fine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants