From a7d5741d1c0dacc150f6b834d69a04a1692e2bf2 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Wed, 1 Nov 2023 12:11:36 -0500 Subject: [PATCH] CE-604 expose fetching MemoizedResult (so nulls can be cached and differentiated from not-founds) --- .../core/utils/memoization/Memoization.java | 31 ++++++++++++++- .../utils/memoization/MemoizedResult.java | 2 +- .../utils/memoization/MemoizationTest.java | 38 +++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/Memoization.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/Memoization.java index df385bd7..e874c5e5 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/Memoization.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/Memoization.java @@ -67,7 +67,26 @@ public class Memoization { if(result.getTime().isAfter(Instant.now().minus(timeout))) { - return (Optional.of(result.getResult())); + return (Optional.ofNullable(result.getResult())); + } + } + + return (Optional.empty()); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public Optional> getMemoizedResult(K key) + { + MemoizedResult result = map.get(key); + if(result != null) + { + if(result.getTime().isAfter(Instant.now().minus(timeout))) + { + return (Optional.ofNullable(result)); } } @@ -122,6 +141,16 @@ public class Memoization + /******************************************************************************* + ** + *******************************************************************************/ + public void clear() + { + this.map.clear(); + } + + + /******************************************************************************* ** Setter for timeoutSeconds ** diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizedResult.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizedResult.java index ba50211e..281e1425 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizedResult.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizedResult.java @@ -29,7 +29,7 @@ import java.time.Instant; ** Object stored in the Memoization class. Shouldn't need to be visible outside ** its package. *******************************************************************************/ -class MemoizedResult +public class MemoizedResult { private T result; private Instant time; diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizationTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizationTest.java index c6858168..85683482 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizationTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/memoization/MemoizationTest.java @@ -26,6 +26,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -36,6 +37,9 @@ import com.kingsrook.qqq.backend.core.utils.SleepUtils; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /******************************************************************************* @@ -84,6 +88,40 @@ class MemoizationTest extends BaseTest + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testCanStoreNull() + { + Memoization memoization = new Memoization<>(); + memoization.storeResult("null", null); + + /////////////////////////////////////////////////////////////////////////////////////////// + // note - we can't tell a stored null apart from a non-stored value by calling getResult // + /////////////////////////////////////////////////////////////////////////////////////////// + Optional optionalNull = memoization.getResult("null"); + assertNotNull(optionalNull); + assertTrue(optionalNull.isEmpty()); + + //////////////////////////////////////////// + // instead, we must use getMemoizedResult // + //////////////////////////////////////////// + Optional> optionalMemoizedResult = memoization.getMemoizedResult("null"); + assertNotNull(optionalMemoizedResult); + assertTrue(optionalMemoizedResult.isPresent()); + assertNull(optionalMemoizedResult.get().getResult()); + + ///////////////////////////////////////////////////////////////// + // make sure getMemoizedResult returns empty for an un-set key // + ///////////////////////////////////////////////////////////////// + optionalMemoizedResult = memoization.getMemoizedResult("never-stored"); + assertNotNull(optionalMemoizedResult); + assertTrue(optionalMemoizedResult.isEmpty()); + } + + + /******************************************************************************* ** *******************************************************************************/