diff --git a/executor/pom.xml b/executor/pom.xml
index 673e6aa..1cc19a1 100644
--- a/executor/pom.xml
+++ b/executor/pom.xml
@@ -49,6 +49,24 @@
4.5.1
test
+
+ org.testcontainers
+ junit-jupiter
+ 1.17.4
+ test
+
+
+ org.testcontainers
+ testcontainers
+ 1.17.4
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ 1.4.5
+ test
+
diff --git a/executor/src/test/java/CacheIT.java b/executor/src/test/java/CacheIT.java
new file mode 100644
index 0000000..45f1ef1
--- /dev/null
+++ b/executor/src/test/java/CacheIT.java
@@ -0,0 +1,173 @@
+import de.rwth.imi.flare.api.model.*;
+import de.rwth.imi.flare.api.model.mapping.AttributeSearchParameter;
+import de.rwth.imi.flare.api.model.mapping.MappingEntry;
+import de.rwth.imi.flare.executor.AuthlessRequestorConfig;
+import de.rwth.imi.flare.executor.FlareExecutor;
+import de.rwth.imi.flare.requestor.*;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.testcontainers.containers.FixedHostPortGenericContainer;
+import org.testcontainers.containers.output.Slf4jLogConsumer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.images.PullPolicy;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executors;
+
+
+@Slf4j
+@Testcontainers
+public class CacheIT {
+
+ FlareExecutor executor;
+ FhirRequestorConfig config;
+ private final int malesToGenerate =15;
+ private final int femalesToGenerate = 1000;
+ private String baseFhirUri;
+ private int idCounter = 0;
+ private String singlePatientTemplate;
+
+ @Container
+ private final FixedHostPortGenericContainer> fhirContainer = new FixedHostPortGenericContainer<>("samply/blaze:0.18")
+ .withImagePullPolicy(PullPolicy.alwaysPull())
+ .withFixedExposedPort(8080, 8080)
+ .waitingFor(Wait.forHttp("/health").forStatusCode(200))
+ .withLogConsumer(new Slf4jLogConsumer(log))
+ .withEnv("LOG_LEVEL", "debug")
+ .withStartupAttempts(5);
+
+ @Test
+ public void mainCacheIntegrationTest() throws Exception {
+ baseFhirUri = "http://localhost:" + fhirContainer.getMappedPort(8080) + "/fhir" ;
+ //baseFhirUri = "http://localhost:8082/fhir"; //overwrite baseFhirUri like this if you want to use your own fhir server
+ singlePatientTemplate = loadSinglePatientTemplate();
+ createExecutor();
+
+ try{
+ uploadTestData();
+ }catch(IOException e){
+ e.printStackTrace();
+ }
+
+ QueryExpanded query = buildGenderQuery("female");
+
+ long startTime1 = System.nanoTime();
+ CompletableFuture compFuture1 = executor.calculatePatientCount(query);
+ int patientCount1 = compFuture1.get();
+ float duration1 = (System.nanoTime() - startTime1) / 1000000.f;
+ assertEquals(femalesToGenerate, patientCount1);
+
+ long startTime2 = System.nanoTime();
+ CompletableFuture compFuture2 = executor.calculatePatientCount(query);
+ int patientCount2 = compFuture2.get();
+ float duration2 = (System.nanoTime() - startTime2) / 1000000.f;
+ assertEquals(femalesToGenerate, patientCount2);
+
+ System.out.println("time not cached: " + duration1 + "ms");
+ System.out.println("time cached: " + duration2 + "ms");
+
+
+ //TODO upload lots of patients to test how long it takes to retrieve lots of patient ids from disk
+ }
+
+
+ private void uploadTestData() throws IOException, InterruptedException {
+
+ for(int i = 0; i < malesToGenerate; i++){
+ String newPatient = generateSinglePatient("male");
+ postPatient(newPatient);
+ }
+
+ for(int i = 0; i < femalesToGenerate; i++){
+ String newPatient = generateSinglePatient("female");
+ postPatient(newPatient);
+ }
+ }
+
+ private void postPatient(String patient) throws IOException, InterruptedException {
+ HttpClient client = HttpClient.newHttpClient();
+ patient = patient.replace("\n", "").replace("\r", "");
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(baseFhirUri))
+ .POST(HttpRequest.BodyPublishers.ofString(patient))
+ .header("Content-Type", "application/fhir+json")
+ .build();
+
+ client.send(request,
+ HttpResponse.BodyHandlers.ofString());
+ }
+
+ private String loadSinglePatientTemplate() throws IOException {
+ String baseFilePath = new File("").getAbsolutePath();
+ Path filePath = Path.of(baseFilePath + "/src/test/java/single-patient-template.json");
+ return Files.readString(filePath);
+ }
+
+ private String generateSinglePatient(String gender) {
+ String newPatient = singlePatientTemplate;
+ newPatient = newPatient.replace("pat-generated-id", String.valueOf(idCounter));
+ newPatient = newPatient.replace("con-generated-id", String.valueOf(idCounter));
+ newPatient = newPatient.replace("obs-generated-id", String.valueOf(idCounter));
+ newPatient = newPatient.replace("enc-generated-id", String.valueOf(idCounter));
+ newPatient = newPatient.replace("", gender);
+ newPatient = newPatient.replace("", "1990-01-01");
+ idCounter++;
+ return newPatient;
+ }
+
+ public void createExecutor() throws URISyntaxException {
+ config = new AuthlessRequestorConfig(new URI(baseFhirUri + "/"), "50", new FlareThreadPoolConfig(4,16,10));
+ executor = new FlareExecutor(new FhirRequestor(config, Executors.newFixedThreadPool(16)));
+ }
+
+ private QueryExpanded buildGenderQuery(String gender) {
+
+ Criterion criterion1 = new Criterion();
+ List femaleTerminology = Arrays.asList(new TerminologyCode("gender", "mii.abide", "Geschlecht"));
+ criterion1.setTermCodes(femaleTerminology);
+
+ MappingEntry mapping = new MappingEntry();
+ AttributeSearchParameter attributeSearchParameter = new AttributeSearchParameter();
+ attributeSearchParameter.setAttributeKey(new TerminologyCode("gender", "mii.abide", "Geschlecht"));
+ attributeSearchParameter.setAttributeFhirPath("gender");
+ attributeSearchParameter.setAttributeType("code");
+ attributeSearchParameter.setAttributeSearchParameter("gender");
+ mapping.setAttributeSearchParameters(List.of(attributeSearchParameter));
+ mapping.setFhirResourceType("Patient");
+ criterion1.setMapping(mapping);
+
+ AttributeFilter femaleAttributeFilter = new AttributeFilter();
+ femaleAttributeFilter.setType(FilterType.CONCEPT);
+ TerminologyCode attributeConcept = new TerminologyCode(gender, "http://hl7.org/fhir/administrative-gender", "someDisplay");
+ femaleAttributeFilter.setSelectedConcepts(List.of(attributeConcept));
+ TerminologyCode femaleAttributeCode = new TerminologyCode("gender", "mii.abide", "Geschlecht");
+ femaleAttributeFilter.setAttributeCode(femaleAttributeCode);
+ List attributeFilters = List.of(femaleAttributeFilter);
+ criterion1.setAttributeFilters(attributeFilters);
+
+ CriteriaGroup criteriaGroup1 = new CriteriaGroup(List.of(criterion1));
+ Query expectedResult = new Query();
+ expectedResult.setInclusionCriteria(List.of(criteriaGroup1));
+ QueryExpanded parsedQuery = new QueryExpanded();
+ parsedQuery.setInclusionCriteria(expectedResult.getInclusionCriteria());
+
+ return parsedQuery;
+ }
+
+}
diff --git a/executor/src/test/java/ExecutorTest.java b/executor/src/test/java/ExecutorTest.java
index 448c685..ba4ad8b 100644
--- a/executor/src/test/java/ExecutorTest.java
+++ b/executor/src/test/java/ExecutorTest.java
@@ -2,7 +2,6 @@
import de.rwth.imi.flare.api.model.mapping.MappingEntry;
import de.rwth.imi.flare.executor.AuthlessRequestorConfig;
import de.rwth.imi.flare.executor.FlareExecutor;
-import de.rwth.imi.flare.requestor.CacheConfig;
import de.rwth.imi.flare.requestor.FhirRequestor;
import de.rwth.imi.flare.requestor.FhirRequestorConfig;
import de.rwth.imi.flare.requestor.FlareThreadPoolConfig;
@@ -26,18 +25,7 @@ public class ExecutorTest
public ExecutorTest() throws URISyntaxException {
config = new AuthlessRequestorConfig(new URI("http://localhost:8080/fhir/"), "50", new FlareThreadPoolConfig(4,16,10));
- CacheConfig cacheConfig = new CacheConfig() {
- @Override
- public int getCacheSizeInMb() {
- return 100;
- }
-
- @Override
- public int getEntryRefreshTimeHours() {
- return 1;
- }
- };
- executor = new FlareExecutor(new FhirRequestor(config, cacheConfig, Executors.newFixedThreadPool(16)));
+ executor = new FlareExecutor(new FhirRequestor(config, Executors.newFixedThreadPool(16)));
}
@Test
diff --git a/executor/src/test/java/ExecutorTests.java b/executor/src/test/java/ExecutorTests.java
index ced7da2..90a7dab 100644
--- a/executor/src/test/java/ExecutorTests.java
+++ b/executor/src/test/java/ExecutorTests.java
@@ -6,7 +6,6 @@
import de.rwth.imi.flare.executor.AuthlessRequestorConfig;
import de.rwth.imi.flare.executor.FhirIdRequestor;
import de.rwth.imi.flare.executor.FlareExecutor;
-import de.rwth.imi.flare.requestor.CacheConfig;
import de.rwth.imi.flare.requestor.FhirRequestor;
import de.rwth.imi.flare.requestor.FlareThreadPoolConfig;
import java.util.concurrent.Executors;
@@ -59,18 +58,8 @@ void setUp() throws URISyntaxException {
AuthlessRequestorConfig config = new AuthlessRequestorConfig(
new URI("http://localhost:8080/fhir/"),
"50", new FlareThreadPoolConfig(4, 16, 10));
- CacheConfig cacheConfig = new CacheConfig() {
- @Override
- public int getCacheSizeInMb() {
- return 100;
- }
-
- @Override
- public int getEntryRefreshTimeHours() {
- return 1;
- }
- };
- flareExecutor = new FlareExecutor(new FhirRequestor(config, cacheConfig, Executors.newFixedThreadPool(16)));
+
+ flareExecutor = new FlareExecutor(new FhirRequestor(config, Executors.newFixedThreadPool(16)));
queryExpanded = getQueryExpanded();
}
diff --git a/executor/src/test/java/single-patient-template.json b/executor/src/test/java/single-patient-template.json
new file mode 100644
index 0000000..b0cc311
--- /dev/null
+++ b/executor/src/test/java/single-patient-template.json
@@ -0,0 +1 @@
+{"resourceType":"Bundle","type":"transaction","entry":[{"fullUrl":"Patient/pat-generated-id","resource":{"resourceType":"Patient","id":"pat-generated-id","meta":{"profile":["https://www.medizininformatik-initiative.de/fhir/core/modul-person/StructureDefinition/Patient"]},"identifier":[{"use":"usual","type":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0203","code":"MR"}]},"system":"https://UKFAU.de/pid","value":"pat-generated-id"}],"name":[{"use":"official","family":"y","given":["x"]}],"gender":"","birthDate":"1990-01-01"},"request":{"method":"PUT","url":"Patient/pat-generated-id"}},{"fullUrl":"Encounter/enc-generated-id","resource":{"resourceType":"Encounter","id":"enc-generated-id","meta":{"profile":["https://www.medizininformatik-initiative.de/fhir/core/modul-fall/StructureDefinition/KontaktGesundheitseinrichtung"]},"identifier":[{"type":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0203","code":"VN"}]},"system":"http://dummyurl","value":"enc-generated-id","assigner":{"identifier":{"system":"https://www.medizininformatik-initiative.de/fhir/core/NamingSystem/org-identifier","value":"UKFAU"}}}],"status":"finished","class":{"system":"http://terminology.hl7.org/CodeSystem/v3-ActCode","code":"IMP","display":"inpatient encounter"},"subject":{"reference":"Patient/pat-generated-id","identifier":{"value":"pat-generated-id"}},"period":{"start":"2020-05-13T00:00:00+02:00","end":"2020-05-18T00:00:00+02:00"}},"request":{"method":"PUT","url":"Encounter/enc-generated-id"}},{"fullUrl":"Condition/con-generated-id","resource":{"resourceType":"Condition","id":"con-generated-id","meta":{"profile":["https://www.medizininformatik-initiative.de/fhir/core/modul-diagnose/StructureDefinition/Diagnose"]},"identifier":[{"value":"con-generated-id","system":"https://UKE.de/condition"}],"code":{"coding":[{"system":"http://fhir.de/CodeSystem/bfarm/icd-10-gm","version":"2020","code":"C50.1"}]},"subject":{"reference":"Patient/pat-generated-id","identifier":{"value":"pat-generated-id"}},"recordedDate":"2018-07-09T02:30:51+02:00","encounter":{"reference":"Encounter/enc-generated-id"},"onsetDateTime":"2018-07-09T02:30:51+02:00"},"request":{"method":"PUT","url":"Condition/con-generated-id"}},{"fullUrl":"Observation/obs-generated-id","resource":{"resourceType":"Observation","id":"obs-generated-id","meta":{"profile":["https://www.medizininformatik-initiative.de/fhir/core/modul-labor/StructureDefinition/ObservationLab"]},"identifier":[{"type":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/v2-0203","code":"OBI"}]},"system":"https://UKE.de/befund","value":"obs-generated-id","assigner":{"identifier":{"system":"https://www.medizininformatik-initiative.de/fhir/core/NamingSystem/org-identifier","value":"UKE"}}}],"status":"final","category":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/observation-category","code":"laboratory","display":"Laboratory"},{"system":"http://loinc.org","code":"26436-6","display":"Laboratory studies (set)"}]}],"code":{"coding":[{"system":"http://loinc.org","code":"55782-7"}]},"subject":{"reference":"Patient/pat-generated-id","identifier":{"value":"pat-generated-id"}},"encounter":{"reference":"Encounter/enc-generated-id","identifier":{"value":"enc-generated-id"}},"effectiveDateTime":"2019-04-12T05:33:27+02:00","valueQuantity":{"value":11.9914,"unit":"gram per deciliter","system":"http://unitsofmeasure.org","code":"g/dL"}},"request":{"method":"PUT","url":"Observation/obs-generated-id"}}]}
diff --git a/executor/src/test/resources/logback-test.xml b/executor/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..9750b9f
--- /dev/null
+++ b/executor/src/test/resources/logback-test.xml
@@ -0,0 +1,15 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
+
+
+
+
+
+
+
+
+
+
+
diff --git a/flare-cli/src/main/java/de/rwth/imi/flare/cli/CLI.java b/flare-cli/src/main/java/de/rwth/imi/flare/cli/CLI.java
index ad13afb..8ec5f08 100644
--- a/flare-cli/src/main/java/de/rwth/imi/flare/cli/CLI.java
+++ b/flare-cli/src/main/java/de/rwth/imi/flare/cli/CLI.java
@@ -12,7 +12,6 @@
import de.rwth.imi.flare.mapping.lookup.NaiveLookupMapping;
import de.rwth.imi.flare.mapping.lookup.SourceMappingEntry;
import de.rwth.imi.flare.parser.i2b2.ParserI2B2;
-import de.rwth.imi.flare.requestor.CacheConfig;
import de.rwth.imi.flare.requestor.FhirRequestor;
import de.rwth.imi.flare.requestor.FhirRequestorConfig;
import de.rwth.imi.flare.requestor.FlareThreadPoolConfig;
@@ -136,19 +135,7 @@ public FlareThreadPoolConfig getThreadPoolConfig() {
};
- CacheConfig cacheConfig = new CacheConfig() {
- @Override
- public int getCacheSizeInMb() {
- return 100;
- }
-
- @Override
- public int getEntryRefreshTimeHours() {
- return 1;
- }
- };
-
- executor = new FlareExecutor(new FhirRequestor(config, cacheConfig, Executors.newFixedThreadPool(16)));
+ executor = new FlareExecutor(new FhirRequestor(config, Executors.newFixedThreadPool(16)));
}
@Nullable
diff --git a/requestor/pom.xml b/requestor/pom.xml
index 6af460c..2221210 100644
--- a/requestor/pom.xml
+++ b/requestor/pom.xml
@@ -59,11 +59,6 @@
5.7.0
test
-
- com.github.ben-manes.caffeine
- caffeine
- 3.1.1
-
org.testcontainers
junit-jupiter
@@ -75,7 +70,17 @@
testcontainers
1.17.4
-
+
+ org.apache.commons
+ commons-jcs3-core
+ 3.0
+
+
+ org.springframework
+ spring-web
+ 5.3.10
+ test
+
diff --git a/requestor/src/main/java/de/rwth/imi/flare/requestor/FhirRequestor.java b/requestor/src/main/java/de/rwth/imi/flare/requestor/FhirRequestor.java
index bb71593..21adbbb 100644
--- a/requestor/src/main/java/de/rwth/imi/flare/requestor/FhirRequestor.java
+++ b/requestor/src/main/java/de/rwth/imi/flare/requestor/FhirRequestor.java
@@ -1,24 +1,26 @@
package de.rwth.imi.flare.requestor;
import ca.uhn.fhir.context.FhirContext;
-import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
-import com.github.benmanes.caffeine.cache.Caffeine;
-import com.github.benmanes.caffeine.cache.RemovalCause;
-import com.github.benmanes.caffeine.cache.Weigher;
import de.rwth.imi.flare.api.FlareResource;
import de.rwth.imi.flare.api.model.Criterion;
import java.net.URI;
import java.net.URISyntaxException;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import lombok.extern.slf4j.Slf4j;
-import org.checkerframework.checker.index.qual.NonNegative;
+import org.apache.commons.jcs3.access.exception.CacheException;
import org.jetbrains.annotations.NotNull;
+import org.apache.commons.jcs3.JCS;
+import org.apache.commons.jcs3.access.CacheAccess;
/**
* Requestor implementation, takes a single criterion, builds a FHIR Query from
@@ -27,28 +29,26 @@
@Slf4j
public class FhirRequestor implements de.rwth.imi.flare.api.Requestor {
- private static final StringSetWeigher WEIGHER = new StringSetWeigher();
- private static final long N_BYTES_IN_MB = 1024*1024;
-
+ private CacheAccess>> cache = null;
+ private final int cacheRefreshTimeInDays = 7;
+ private HashMap>> currentlyRequestingQueries = new HashMap>>();
private final FhirRequestorConfig config;
private final FhirContext fhirR4Context = FhirContext.forR4();
- private final AsyncLoadingCache> cache;
+ private final Executor executor;
/**
* @param executor
* @param requestorConfig Configuration to be used when crafting requests
*/
- public FhirRequestor(FhirRequestorConfig requestorConfig,
- CacheConfig cacheConfig, Executor executor) {
+ public FhirRequestor(FhirRequestorConfig requestorConfig, Executor executor) {
+ this.executor = executor;
this.config = requestorConfig;
- this.cache = Caffeine.newBuilder()
- .maximumWeight(cacheConfig.getCacheSizeInMb() * N_BYTES_IN_MB)
- .weigher(WEIGHER)
- .refreshAfterWrite(cacheConfig.getEntryRefreshTimeHours(), TimeUnit.HOURS)
- .executor(executor)
- .evictionListener((String key, Set idSet, RemovalCause cause) ->
- log.debug("Key " + key + " was evicted, cause: " + cause))
- .buildAsync(this::getSetCompletableFuture);
+ try{
+ this.cache = JCS.getInstance("default");
+ }catch(CacheException e){
+ log.debug("Problem initializing cache: {}", e.getMessage() );
+ }
+
}
@@ -67,16 +67,32 @@ public CompletableFuture> execute(Criterion searchCriterion) {
} catch (URISyntaxException | IncorrectQueryInputException e) {
throw new RuntimeException(e);
}
+
String urlString = requestUrl.toString();
- return cache.get(urlString);
+ CompletableFuture> ongoingRequest = currentlyRequestingQueries.get(urlString);
+ if (ongoingRequest != null) {
+ log.debug("Same request ongoing. Not starting new request");
+ return ongoingRequest;
+ }
+ HashMap> cacheEntry = cache.get(urlString); //this won't work if the base url changed in the meantime (e.g. different port because of testcontainers)
+ if(cacheEntry != null){
+ if(mustRefreshEntry(cacheEntry)) {
+ log.debug("Url " + urlString + " cached, but too long ago. Requesting again...");
+ return getSetFlareStream(urlString,this.executor);
+ }
+ return CompletableFuture.completedFuture(cacheEntry.get("ids"));
+ }else{
+ return getSetFlareStream(urlString, this.executor);
}
+ }
+
@NotNull
- private CompletableFuture> getSetCompletableFuture(String requestUrl, Executor executor) {
+ private CompletableFuture> getSetFlareStream(String requestUrl, Executor executor) {
log.debug("FHIR Search: " + requestUrl + " not cached or refreshing...");
- return CompletableFuture.supplyAsync(() -> {
+ CompletableFuture> compFuture = CompletableFuture.supplyAsync(() -> {
String pagecount = this.config.getPageCount();
FhirSearchRequest fhirSearchRequest = this.config.getAuthentication()
.map((auth) -> new FhirSearchRequest(URI.create(requestUrl), auth, pagecount, fhirR4Context))
@@ -85,8 +101,35 @@ private CompletableFuture> getSetCompletableFuture(String requestUrl
.map(FlareResource::getPatientId)
.collect(Collectors.toSet());
log.debug("FHIR Search: " + requestUrl + " finished execution, writing to cache...");
+
+ putIdsInCache(requestUrl, flareStream);
return flareStream;
}, executor);
+
+ this.currentlyRequestingQueries.put(requestUrl, compFuture);
+ log.debug("Noted url " + requestUrl + " as ongoing request");
+ compFuture.thenApply(s -> {
+ this.currentlyRequestingQueries.remove(requestUrl);
+ log.debug("removed url " + requestUrl + " from ongoing requests");
+ return s;});
+
+ return compFuture;
+ }
+
+ private void putIdsInCache(String requestUrl, Set flareStream){
+ HashMap> hashMap = new HashMap>();
+ hashMap.put("ids", flareStream);
+ hashMap.put("lastRefreshTime", new HashSet(List.of(LocalDateTime.now().toString())));
+ cache.put(requestUrl, hashMap);
+ }
+
+ private boolean mustRefreshEntry(HashMap> cacheEntry){
+ LocalDateTime lastRequestTime = LocalDateTime.parse(cacheEntry.get("lastRefreshTime").toArray()[0].toString());
+ long timeSinceLastRequest = Duration.between(lastRequestTime, LocalDateTime.now()).toDays();
+ if(timeSinceLastRequest > cacheRefreshTimeInDays){
+ return true;
+ }
+ return false;
}
/**
@@ -123,26 +166,4 @@ private URI buildRequestUrl(Criterion search)
return new URI(searchUrl);
}
- private static class StringSetWeigher implements
- Weigher> {
-
- @Override
- public @NonNegative int weigh(String key, Set idSet) {
-
- return calcStringMemUsage(key) + (idSet.isEmpty() ? 88:
- calSetItemMemUsage(calcStringMemUsage(idSet.iterator().next())) * idSet.size());
-
- }
-
- private int calSetItemMemUsage(int elemMemUsage){
- // 44 = HashMapNode, 16 = table array allocation
- return 44 + 16 + elemMemUsage;
- }
-
- private int calcStringMemUsage(String s){
- //30 = StringHeader, 24 = ByteArrayHeader
- return 30 + 24 + s.length();
-
- }
- }
}
diff --git a/requestor/src/main/resources/cache.ccf b/requestor/src/main/resources/cache.ccf
new file mode 100644
index 0000000..7d1aee1
--- /dev/null
+++ b/requestor/src/main/resources/cache.ccf
@@ -0,0 +1,19 @@
+##############################################################
+##### Default Region Configuration
+jcs.default=DC
+jcs.default.cacheattributes=org.apache.commons.jcs3.engine.CompositeCacheAttributes
+jcs.default.cacheattributes.MaxObjects=0
+jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs3.engine.memory.lru.LRUMemoryCache
+
+
+##############################################################
+##### AUXILIARY CACHES
+# Indexed Disk Cache
+jcs.auxiliary.DC=org.apache.commons.jcs3.auxiliary.disk.indexed.IndexedDiskCacheFactory
+jcs.auxiliary.DC.attributes=org.apache.commons.jcs3.auxiliary.disk.indexed.IndexedDiskCacheAttributes
+jcs.auxiliary.DC.attributes.DiskPath=target/jcs-cache-db
+jcs.auxiliary.DC.attributes.MaxPurgatorySize=10000
+jcs.auxiliary.DC.attributes.MaxKeySize=10
+jcs.auxiliary.DC.attributes.OptimizeAtRemoveCount=300000
+jcs.auxiliary.DC.attributes.OptimizeOnShutdown=true
+jcs.auxiliary.DC.attributes.DiskLimitType=COUNT
\ No newline at end of file
diff --git a/requestor/src/test/java/patient-age-testdata.ndjson b/requestor/src/test/java/patient-age-testdata.ndjson
deleted file mode 100644
index 2f76c36..0000000
--- a/requestor/src/test/java/patient-age-testdata.ndjson
+++ /dev/null
@@ -1 +0,0 @@
-{"resourceType": "Bundle", "type": "transaction", "entry": [{"fullUrl": "Patient/pat-generated-id-1", "resource": {"resourceType": "Patient", "id": "pat-generated-id-1", "meta": {"profile": ["https://www.medizininformatik-initiative.de/fhir/core/modul-person/StructureDefinition/Patient"]}, "identifier": [{"use": "usual", "type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MR"}]}, "system": "https://UKFAU.de/pid", "value": "pat-generated-id-1"}], "name": [{"use": "official", "family": "y", "given": ["x"]}], "gender": "other", "birthDate": "1983-05-17"}, "request": {"method": "PUT", "url": "Patient/pat-generated-id-1"}}, {"fullUrl": "Patient/pat-generated-id-2", "resource": {"resourceType": "Patient", "id": "pat-generated-id-2", "meta": {"profile": ["https://www.medizininformatik-initiative.de/fhir/core/modul-person/StructureDefinition/Patient"]}, "identifier": [{"use": "usual", "type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MR"}]}, "system": "https://UKFAU.de/pid", "value": "pat-generated-id-2"}], "name": [{"use": "official", "family": "y", "given": ["x"]}], "gender": "other", "birthDate": "1990-01-01"}, "request": {"method": "PUT", "url": "Patient/pat-generated-id-2"}}, {"fullUrl": "Patient/pat-generated-id-3", "resource": {"resourceType": "Patient", "id": "pat-generated-id-3", "meta": {"profile": ["https://www.medizininformatik-initiative.de/fhir/core/modul-person/StructureDefinition/Patient"]}, "identifier": [{"use": "usual", "type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MR"}]}, "system": "https://UKFAU.de/pid", "value": "pat-generated-id-3"}], "name": [{"use": "official", "family": "y", "given": ["x"]}], "gender": "other", "birthDate": "1990-11-01"}, "request": {"method": "PUT", "url": "Patient/pat-generated-id-3"}}, {"fullUrl": "Patient/pat-generated-id-4", "resource": {"resourceType": "Patient", "id": "pat-generated-id-4", "meta": {"profile": ["https://www.medizininformatik-initiative.de/fhir/core/modul-person/StructureDefinition/Patient"]}, "identifier": [{"use": "usual", "type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MR"}]}, "system": "https://UKFAU.de/pid", "value": "pat-generated-id-4"}], "name": [{"use": "official", "family": "y", "given": ["x"]}], "gender": "other", "birthDate": "2022-10-01"}, "request": {"method": "PUT", "url": "Patient/pat-generated-id-4"}}, {"fullUrl": "Patient/pat-generated-id-5", "resource": {"resourceType": "Patient", "id": "pat-generated-id-5", "meta": {"profile": ["https://www.medizininformatik-initiative.de/fhir/core/modul-person/StructureDefinition/Patient"]}, "identifier": [{"use": "usual", "type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MR"}]}, "system": "https://UKFAU.de/pid", "value": "pat-generated-id-5"}], "name": [{"use": "official", "family": "y", "given": ["x"]}], "gender": "other", "birthDate": "2022-11-01"}, "request": {"method": "PUT", "url": "Patient/pat-generated-id-5"}}]}
\ No newline at end of file
diff --git a/server/src/main/java/de/rwth/imi/flare/server/configuration/FlareAlgorithmConfiguration.java b/server/src/main/java/de/rwth/imi/flare/server/configuration/FlareAlgorithmConfiguration.java
index 889e205..5a3f10e 100644
--- a/server/src/main/java/de/rwth/imi/flare/server/configuration/FlareAlgorithmConfiguration.java
+++ b/server/src/main/java/de/rwth/imi/flare/server/configuration/FlareAlgorithmConfiguration.java
@@ -11,7 +11,6 @@
import de.rwth.imi.flare.mapping.expansion.QueryExpander;
import de.rwth.imi.flare.mapping.lookup.NaiveLookupMapping;
import de.rwth.imi.flare.mapping.lookup.SourceMappingEntry;
-import de.rwth.imi.flare.requestor.CacheConfig;
import de.rwth.imi.flare.requestor.FhirRequestor;
import de.rwth.imi.flare.requestor.FhirRequestorConfig;
import de.rwth.imi.flare.requestor.FlareThreadPoolConfig;
@@ -92,9 +91,7 @@ protected PasswordAuthentication getPasswordAuthentication() {
public Executor executor(@Nullable Authenticator auth,
@Value("${flare.fhir.server}") String fhirBaseUri, @Value("${flare.fhir.pagecount}") String fhirSearchPageCount,
@Value("${flare.exec.corePoolSize}") int corePoolSize, @Value("${flare.exec.maxPoolSize}") int maxPoolSize,
- @Value("${flare.exec.keepAliveTimeSeconds}") int keepAliveTimeSeconds,
- @Value("${flare.cache.cacheSizeMb}") int cacheSizeMb,
- @Value("${flare.cache.entryRefreshTimeHours}") int entryRefreshTimeHours) {
+ @Value("${flare.exec.keepAliveTimeSeconds}") int keepAliveTimeSeconds) {
FhirRequestorConfig config = new FhirRequestorConfig() {
@Override
@@ -124,21 +121,9 @@ public FlareThreadPoolConfig getThreadPoolConfig() {
keepAliveTimeSeconds);
}
};
- CacheConfig cacheConfig = new CacheConfig() {
- @Override
- public int getCacheSizeInMb() {
- return cacheSizeMb;
- }
-
- @Override
- public int getEntryRefreshTimeHours() {
- return entryRefreshTimeHours;
- }
-
- };
- return new FlareExecutor(new FhirRequestor(config, cacheConfig, Executors.newFixedThreadPool(maxPoolSize)));
+ return new FlareExecutor(new FhirRequestor(config, Executors.newFixedThreadPool(maxPoolSize)));
}