From 15e9ba30f0d8518bed23ff82282c01ea1c5de8e1 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 18 Jun 2024 17:30:12 -0400 Subject: [PATCH] Change to explicitly 'expiring' the oldest session. --- ... ExplicitExpirySessionCacheDecorator.java} | 35 +++++++------ .../MaxSizeSessionCacheDecoratorTest.java | 51 +++++++++++++++---- 2 files changed, 60 insertions(+), 26 deletions(-) rename org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/{MaxSizeSessionCacheDecorator.java => ExplicitExpirySessionCacheDecorator.java} (70%) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/MaxSizeSessionCacheDecorator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ExplicitExpirySessionCacheDecorator.java similarity index 70% rename from org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/MaxSizeSessionCacheDecorator.java rename to org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ExplicitExpirySessionCacheDecorator.java index 73d16e9f0..9b6697a96 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/MaxSizeSessionCacheDecorator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/ExplicitExpirySessionCacheDecorator.java @@ -7,25 +7,31 @@ import java.util.List; import java.util.Set; import java.util.function.Supplier; -public class MaxSizeSessionCacheDecorator implements SessionCache { +public class ExplicitExpirySessionCacheDecorator implements SessionCache { + - public final int maxSize; public final SessionCache sessionCache; private final List sessionIds; - public MaxSizeSessionCacheDecorator(SessionCache sessionCache, int maxSize) { + public ExplicitExpirySessionCacheDecorator(SessionCache sessionCache) { this.sessionCache = sessionCache; - this.maxSize = maxSize; this.sessionIds = new ArrayList<>(sessionCache.getSessionIds()); - if (this.sessionIds.size() > maxSize) { - throw new IllegalArgumentException("Session cache size exceeds the maximum size"); + } + + public boolean expireOldestSession() { + if (sessionIds.isEmpty()) { + return false; } + String oldestSessionId = sessionIds.get(0); + sessionIds.remove(oldestSessionId); + sessionCache.removeSession(oldestSessionId); + return true; } @Override public String cacheSession(ValidationEngine validationEngine) { - checkSizeAndMaintainMax(null); + maintainSessionIds(null); String key = sessionCache.cacheSession(validationEngine); sessionIds.add(key); return key; @@ -33,12 +39,14 @@ public class MaxSizeSessionCacheDecorator implements SessionCache { @Override public String cacheSession(Supplier validationEngineSupplier) { - checkSizeAndMaintainMax(null); + maintainSessionIds(null); ValidationEngine validationEngine = validationEngineSupplier.get(); - return sessionCache.cacheSession(validationEngine); + String key = sessionCache.cacheSession(validationEngine); + sessionIds.add(key); + return key; } - private void checkSizeAndMaintainMax(String keyToAdd) { + private void maintainSessionIds(String keyToAdd) { if (keyToAdd != null || sessionCache.sessionExists(keyToAdd)) { return; } @@ -46,16 +54,11 @@ public class MaxSizeSessionCacheDecorator implements SessionCache { //Sync our tracked keys, in case the underlying cache has changed this.sessionIds.removeIf(key -> !sessionIds.contains(key)); - if (this.sessionIds.size() >= maxSize) { - final String key = this.sessionIds.remove(0); - sessionCache.removeSession(key); - } } @Override public String cacheSession(String sessionId, ValidationEngine validationEngine) { - checkSizeAndMaintainMax(sessionId); - cacheSession(sessionId, validationEngine); + maintainSessionIds(sessionId); return sessionCache.cacheSession( sessionId, validationEngine); } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/cli/services/MaxSizeSessionCacheDecoratorTest.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/cli/services/MaxSizeSessionCacheDecoratorTest.java index 646e6bf79..63db66546 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/cli/services/MaxSizeSessionCacheDecoratorTest.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/cli/services/MaxSizeSessionCacheDecoratorTest.java @@ -32,23 +32,54 @@ public class MaxSizeSessionCacheDecoratorTest { } @Test - public void trivialCase() { + public void trivialExpiryTest() { - MaxSizeSessionCacheDecorator maxSizeSessionCacheDecorator = new MaxSizeSessionCacheDecorator(new PassiveExpiringSessionCache(), 4); + ExplicitExpirySessionCacheDecorator sessionCache = new ExplicitExpirySessionCacheDecorator(new PassiveExpiringSessionCache()); - LinkedHashMap initialEngines = addMockedEngines(maxSizeSessionCacheDecorator, 3); + LinkedHashMap initialEngines = addMockedEngines(sessionCache, 3); - Assertions.assertEquals(3, maxSizeSessionCacheDecorator.getSessionIds().size()); + Assertions.assertEquals(3, sessionCache.getSessionIds().size()); - LinkedHashMap newEngines = addMockedEngines(maxSizeSessionCacheDecorator, 2); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 0))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 1))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 2))); + Assertions.assertTrue(sessionCache.expireOldestSession()); - Assertions.assertEquals(4, maxSizeSessionCacheDecorator.getSessionIds().size()); - Assertions.assertTrue(maxSizeSessionCacheDecorator.getSessionIds().contains(getKeyByIndex(initialEngines, 1))); - Assertions.assertTrue(maxSizeSessionCacheDecorator.getSessionIds().contains(getKeyByIndex(initialEngines, 2))); - Assertions.assertTrue(maxSizeSessionCacheDecorator.getSessionIds().contains(getKeyByIndex(newEngines, 0))); - Assertions.assertTrue(maxSizeSessionCacheDecorator.getSessionIds().contains(getKeyByIndex(newEngines, 1))); + Assertions.assertEquals(2, sessionCache.getSessionIds().size()); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 1))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 2))); + LinkedHashMap newEngines = addMockedEngines(sessionCache, 2); + + Assertions.assertEquals(4, sessionCache.getSessionIds().size()); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 1))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 2))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(newEngines, 0))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(newEngines, 1))); + + Assertions.assertTrue(sessionCache.expireOldestSession()); + + Assertions.assertEquals(3, sessionCache.getSessionIds().size()); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(initialEngines, 2))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(newEngines, 0))); + Assertions.assertTrue(sessionCache.getSessionIds().contains(getKeyByIndex(newEngines, 1))); + + Assertions.assertTrue(sessionCache.expireOldestSession()); + Assertions.assertTrue(sessionCache.expireOldestSession()); + Assertions.assertTrue(sessionCache.expireOldestSession()); + Assertions.assertFalse(sessionCache.expireOldestSession()); + } + + @Test + public void producerAddTest() { + ExplicitExpirySessionCacheDecorator maxSizeSessionCacheDecorator = new ExplicitExpirySessionCacheDecorator(new PassiveExpiringSessionCache()); + ValidationEngine producedEngine = mock(ValidationEngine.class); + String sessionId = maxSizeSessionCacheDecorator.cacheSession(() -> { + return producedEngine; + }); + Assertions.assertEquals(1, maxSizeSessionCacheDecorator.getSessionIds().size()); + Assertions.assertSame(producedEngine, maxSizeSessionCacheDecorator.fetchSessionValidatorEngine(sessionId)); } private String getKeyByIndex(LinkedHashMap engineMap, int index) {