LinuxForHealth / FHIR

The LinuxForHealth FHIR® Server and related projects
https://linuxforhealth.github.io/FHIR
Apache License 2.0
330 stars 157 forks source link

Add cleaner framework for RegistryResourceProvider impls to utilize the registry #2975

Open lmsurpre opened 2 years ago

lmsurpre commented 2 years ago

Is your feature request related to a problem? Please describe. In https://github.com/IBM/FHIR/issues/2970 we added an overloaded getResource method that takes the canonical class name of a provider that we want to skip.

This was the most logical/straightforward way to allow a RegistryResourceProvider to load resources that it depends on (e.g. #2969).

However, while brainstorming with Paul, we though of an alternative that feels a little cleaner to me...

Describe the solution you'd like

  1. Introduce a new method named getRegistryResourceDependencies on FHIRRegistryResourceProvider that will return a set of [resource type, canonical URL] pairs for resources that this resource provider depends on. Each canonical url is a url with an optional version...either as a single string (url|version) or as separate fields. For example, if we go the single string route:

    public Map<String, Set<String>> getRegistryResourceDependencies()
  2. The FHIRRegistry implementation will collect these registryResourceDependendencies and avoid calling the FHIRRegistryResourceProvider's init method until all of these FHIRRegistryResources are available in the registry.

  3. Further, the registry will pass these FHIRRegistryResources to the FHIRRegistryResourceProvider implementation as part of its init call.

    public void init(Set<FHIRRegistryResource>)
  4. The FHIRRegistry will track whether each provider has been inited or not and it will only ask for resources from FHIRRegistryResourceProvider implementations that have been.

This way, a FHIRRegistryResourceProvider can depend on other resources in the registry without actually invoking registry methods like getResource (and we can remove that overloaded getResource method that takes the canonical class name).

Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

Acceptance Criteria

  1. GIVEN [a precondition] AND [another precondition] WHEN [test step] AND [test step] THEN [verification step] AND [verification step]

Additional context One tricky part to this is "when should the registry check if a given provider's dependencies are available?" For providers with no dependencies, we could init them right away right from loadProviders(). For others, we could collect their dependencies into a structure that would let us easily:

  1. get a list of the unmet dependency urls for each provider; and
  2. get the actual registry resources once we have them all (to call that provider's init)

Then, when someone invokes FHIRRegistry.init(), we loop through all the providers and try to meet their dependencies. When we find the last dependency for one, we call that one's init. After each init, we check that one to see if it has any of the other dependencies we're still looking for.

Note: we'd also need to call init for any resource providers added directly via FHIRRegistry.addProvider()...which could potentially resolve the dependencies for any other providers that havn't been inited yet.

prb112 commented 2 years ago

I 100% agree. It's a nice idea, and I think it makes sense.