diff --git a/common/src/main/java/org/opencds/cqf/common/config/FhirServerConfig.java b/common/src/main/java/org/opencds/cqf/common/config/FhirServerConfig.java index 4063b8f53..a54ccc7b9 100644 --- a/common/src/main/java/org/opencds/cqf/common/config/FhirServerConfig.java +++ b/common/src/main/java/org/opencds/cqf/common/config/FhirServerConfig.java @@ -6,9 +6,11 @@ import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; +import com.google.gson.JsonArray; import org.apache.commons.dbcp2.BasicDataSource; import org.cqframework.cql.cql2elm.model.Model; @@ -199,4 +201,31 @@ Map globalModelCache() { Map globalLibraryCache() { return new ConcurrentHashMap(); } + + @Bean(name="globalCdsServiceCache") + AtomicReference cdsServiceCache(){ + return new AtomicReference<>(); + } + + @Bean + public IResourceChangeListener PlanDefinitionChangeListener(IResourceChangeListenerRegistry resourceChangeListenerRegistry, AtomicReference cdsServiceCache) { + IResourceChangeListener listener = new IResourceChangeListener(){ + + @Override + public void handleInit(Collection theResourceIds) { + // Intentionally empty + } + + // TODO: Selectively clear by url. Requires a lookup on the resource + @Override + public void handleChange(IResourceChangeEvent theResourceChangeEvent) { + cdsServiceCache.set(null); + } + }; + + resourceChangeListenerRegistry.registerResourceResourceChangeListener("PlanDefinition", SearchParameterMap.newSynchronous(), listener, 1000); + + return listener; + } + } diff --git a/dstu3/src/main/java/org/opencds/cqf/dstu3/servlet/CdsHooksServlet.java b/dstu3/src/main/java/org/opencds/cqf/dstu3/servlet/CdsHooksServlet.java index 628cd471a..f54646d46 100644 --- a/dstu3/src/main/java/org/opencds/cqf/dstu3/servlet/CdsHooksServlet.java +++ b/dstu3/src/main/java/org/opencds/cqf/dstu3/servlet/CdsHooksServlet.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; @@ -78,6 +79,8 @@ public class CdsHooksServlet extends HttpServlet { private LibraryHelper libraryHelper; + private AtomicReference services; + @SuppressWarnings("unchecked") @Override public void init() { @@ -92,6 +95,7 @@ public void init() { this.serverTerminologyProvider = appCtx.getBean(TerminologyProvider.class); this.modelResolver = appCtx.getBean("dstu3ModelResolver", ModelResolver.class); this.libraryHelper = appCtx.getBean(LibraryHelper.class); + this.services = appCtx.getBean("globalCdsServiceCache", AtomicReference.class); } protected ProviderConfiguration getProviderConfiguration() { @@ -277,8 +281,18 @@ private void printStackTrack(Exception e, HttpServletResponse response) throws I response.getWriter().println(exceptionAsString); } + private JsonArray getServicesArray() { + JsonArray cachedServices = this.services.get(); + if (cachedServices == null || cachedServices.size() == 0) { + cachedServices = getServices().get("services").getAsJsonArray(); + services.set(cachedServices); + } + + return cachedServices; + } + private JsonObject getService(String service) { - JsonArray services = getServices().get("services").getAsJsonArray(); + JsonArray services = getServicesArray(); List ids = new ArrayList<>(); for (JsonElement element : services) { if (element.isJsonObject() && element.getAsJsonObject().has("id")) { diff --git a/r4/src/main/java/org/opencds/cqf/r4/helpers/LibraryHelper.java b/r4/src/main/java/org/opencds/cqf/r4/helpers/LibraryHelper.java index 971142be6..5dcdd0217 100644 --- a/r4/src/main/java/org/opencds/cqf/r4/helpers/LibraryHelper.java +++ b/r4/src/main/java/org/opencds/cqf/r4/helpers/LibraryHelper.java @@ -72,31 +72,6 @@ public org.opencds.cqf.cql.engine.execution.LibraryLoader createLibraryLoader( TranslatingLibraryLoader translatingLibraryLoader = new TranslatingLibraryLoader(modelManager, contentProviders, translatorOptions); - return new CacheAwareLibraryLoaderDecorator(translatingLibraryLoader, libraryCache) { - @Override - protected Boolean translatorOptionsMatch(Library library) { - return true; - } - }; - } - - @Override - public org.opencds.cqf.cql.engine.execution.LibraryLoader createLibraryLoader( - org.cqframework.cql.cql2elm.LibrarySourceProvider provider) { - ModelManager modelManager = new CacheAwareModelManager(this.modelCache); - LibraryManager libraryManager = new LibraryManager(modelManager); - libraryManager.getLibrarySourceLoader().clearProviders(); - - libraryManager.getLibrarySourceLoader().registerProvider(provider); - - TranslatingLibraryLoader translatingLibraryLoader = new TranslatingLibraryLoader(modelManager, null, - translatorOptions); - - return new CacheAwareLibraryLoaderDecorator(translatingLibraryLoader, libraryCache) { - @Override - protected Boolean translatorOptionsMatch(Library library) { - return true; - } - }; + return new CacheAwareLibraryLoaderDecorator(translatingLibraryLoader, libraryCache); } } diff --git a/r4/src/main/java/org/opencds/cqf/r4/servlet/CdsHooksServlet.java b/r4/src/main/java/org/opencds/cqf/r4/servlet/CdsHooksServlet.java index 8f0bd4143..c0ffae066 100644 --- a/r4/src/main/java/org/opencds/cqf/r4/servlet/CdsHooksServlet.java +++ b/r4/src/main/java/org/opencds/cqf/r4/servlet/CdsHooksServlet.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; @@ -78,6 +79,8 @@ public class CdsHooksServlet extends HttpServlet { private LibraryHelper libraryHelper; + private AtomicReference services; + @SuppressWarnings("unchecked") @Override public void init() { @@ -92,6 +95,7 @@ public void init() { this.serverTerminologyProvider = appCtx.getBean(TerminologyProvider.class); this.modelResolver = appCtx.getBean("r4ModelResolver", ModelResolver.class); this.libraryHelper = appCtx.getBean(LibraryHelper.class); + this.services = appCtx.getBean("globalCdsServiceCache", AtomicReference.class); } protected ProviderConfiguration getProviderConfiguration() { @@ -284,7 +288,7 @@ private void printStackTrack(Exception e, HttpServletResponse response) throws I } private JsonObject getService(String service) { - JsonArray services = getServices().get("services").getAsJsonArray(); + JsonArray services = getServicesArray(); List ids = new ArrayList<>(); for (JsonElement element : services) { if (element.isJsonObject() && element.getAsJsonObject().has("id")) { @@ -298,6 +302,16 @@ private JsonObject getService(String service) { "Cannot resolve service: " + service + "\nAvailable services: " + ids.toString()); } + private JsonArray getServicesArray() { + JsonArray cachedServices = this.services.get(); + if (cachedServices == null || cachedServices.size() == 0) { + cachedServices = getServices().get("services").getAsJsonArray(); + services.set(cachedServices); + } + + return cachedServices; + } + private JsonObject getServices() { DiscoveryResolutionR4 discoveryResolutionR4 = new DiscoveryResolutionR4( FhirContext.forCached(FhirVersionEnum.R4).newRestfulGenericClient(HapiProperties.getServerAddress()));