From 29aefa52d0c1c075c4f6ff517d01b71c409e59c2 Mon Sep 17 00:00:00 2001 From: Jonathan Percival Date: Fri, 17 Sep 2021 18:48:57 -0600 Subject: [PATCH 1/3] Cache cds-service definitions --- .../cqf/common/config/FhirServerConfig.java | 29 +++++++++++++++++++ .../cqf/dstu3/servlet/CdsHooksServlet.java | 16 +++++++++- .../opencds/cqf/r4/helpers/LibraryHelper.java | 27 +---------------- .../cqf/r4/servlet/CdsHooksServlet.java | 16 +++++++++- 4 files changed, 60 insertions(+), 28 deletions(-) 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..21cd14cd3 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 = 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..ae073513b 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 = getServices().get("services").getAsJsonArray(); + services.set(cachedServices); + } + + return cachedServices; + } + private JsonObject getServices() { DiscoveryResolutionR4 discoveryResolutionR4 = new DiscoveryResolutionR4( FhirContext.forCached(FhirVersionEnum.R4).newRestfulGenericClient(HapiProperties.getServerAddress())); From 3cf017576681f48d8654cda3bf4d8eb86368cb05 Mon Sep 17 00:00:00 2001 From: Adam Stevenson Date: Sat, 25 Sep 2021 09:21:43 -0600 Subject: [PATCH 2/3] Added size check on cachedServices cache check --- .../java/org/opencds/cqf/dstu3/servlet/CdsHooksServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 21cd14cd3..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 @@ -283,7 +283,7 @@ private void printStackTrack(Exception e, HttpServletResponse response) throws I private JsonArray getServicesArray() { JsonArray cachedServices = this.services.get(); - if (cachedServices == null) { + if (cachedServices == null || cachedServices.size() == 0) { cachedServices = getServices().get("services").getAsJsonArray(); services.set(cachedServices); } From c0af9ecfc4373b56ec90a26d31bfe12a10efa914 Mon Sep 17 00:00:00 2001 From: Jonathan Percival Date: Tue, 28 Sep 2021 11:51:09 -0600 Subject: [PATCH 3/3] Add check for empty cached services --- .../main/java/org/opencds/cqf/r4/servlet/CdsHooksServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ae073513b..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 @@ -304,7 +304,7 @@ private JsonObject getService(String service) { private JsonArray getServicesArray() { JsonArray cachedServices = this.services.get(); - if (cachedServices == null) { + if (cachedServices == null || cachedServices.size() == 0) { cachedServices = getServices().get("services").getAsJsonArray(); services.set(cachedServices); }