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

Should FHIRPath support non-standard properties #4177

Open
codyebberson opened this issue Mar 17, 2024 · 1 comment
Open

Should FHIRPath support non-standard properties #4177

codyebberson opened this issue Mar 17, 2024 · 1 comment

Comments

@codyebberson
Copy link
Member

A long time ago, we explicitly enabled reading non-standard properties via FHIRPath. IIRC, the motivating use case was using FHIRPath to read GraphQL properties.

Original PR: #708

Example:

  test('GraphQL embedded queries', () => {
    const observations: Observation[] = [
      {
        resourceType: 'Observation',
        code: { coding: [{ code: 'ALB' }] },
        valueQuantity: { value: 120, unit: 'ng/dL' },
      },
      {
        resourceType: 'Observation',
        code: { coding: [{ code: 'HBA1C' }] },
        valueQuantity: { value: 5, unit: '%' },
      },
    ];

    // This is an example of how FHIR GraphQL returns embedded searches.
    // The "ObservationList" is not a real property, but a search result.
    const serviceRequest: ServiceRequest = {
      resourceType: 'ServiceRequest',
      ObservationList: observations,
    } as ServiceRequest;

    const query = "ObservationList.where(code.coding[0].code='HBA1C').value";
    const result = evalFhirPathTyped(query, [toTypedValue(serviceRequest)]);
    expect(result).toEqual([
      {
        type: PropertyType.Quantity,
        value: { value: 5, unit: '%' },
      },
    ]);
  });

That works today.

The reason I ask this question is that I recently ran a server profiling exercise, and noticed one of the highest CPU uses is getTypedPropertyValueWithoutSchema. The thing is, getTypedPropertyValueWithoutSchema isn't supposed to be called from the server at all, because the server will always have the schema loaded. getTypedPropertyValueWithoutSchema is an escape hatch for client-side code which may not have all StructureDefinition resources loaded.

It turns out that we're hitting the getTypedPropertyValueWithoutSchema due to the individual-birthdate SearchParameter.

Consider the input: { "resourceType": "Patient", "birthDate": "1990-01-01" }

Consider the FHIRPath expression: Patient.birthDate | Person.birthDate | RelatedPerson.birthDate

Our FHIRPath engine evaluates each branch of the union:

  1. Patient.birthDate
    1. Evaluates Patient - matches the current resourceType, and carries on
    2. Evaluates birthDate - reads the value
  2. Person.birthDate
    1. Evaluates Person - does not match resourceType, so tries to read Person as a property (this could be skipped)
  3. RelatedPerson.birthDate
    1. Evaluates RelatedPerson - does not match resourceType, so tries to read RelatedPerson as a property (this could be skipped)

Reading unrecognized properties is particularly expensive in getTypedPropertyValueWithoutSchema because it needs to try a bunch of choice-of-type [x] permutations. Ultimately, this ends up being a bunch of wasted effort.

So... We are ultimately burning a lot of CPU to support non-standard FHIRPath properties.

If we need to preserve this behavior, there are probably some other potential solutions:

  • Make non-standard properties an option input to the FHIRPath engine
  • Only evaluate choice-of-type [x] code path when the token is lower case (which does have semantic meaning in FHIR)
  • Manually optimize the SearchParameter expressions - the FHIR spec likes to use the | union operator, but that's suboptimal for runtime performance. We could flatten those out.
@codyebberson
Copy link
Member Author

Manually optimize the SearchParameter expressions - the FHIR spec likes to use the | union operator, but that's suboptimal for runtime performance. We could flatten those out.

Actually, this could be done at runtime in the getSearchParameterDetails code. That is the low hanging fruit here.

@codyebberson codyebberson added this to the Milestone Quality milestone Apr 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

1 participant