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))); }