mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Add getResultThrowing; remove Deprecated getResult
This commit is contained in:
@ -58,42 +58,15 @@ public class Memoization<K, V>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Get the memoized Value for a given input Key.
|
|
||||||
**
|
|
||||||
** But note, this looks the same to the caller, whether the key just wasn't in
|
|
||||||
** the internal map (e.g., had never been looked up), or if it was previously looked
|
|
||||||
** up, and that returned null. In either case, the optional will be empty.
|
|
||||||
**
|
|
||||||
** See getMemoizedResult for where we can tell the difference (and we would
|
|
||||||
** generally want to call that.
|
|
||||||
*******************************************************************************/
|
|
||||||
@Deprecated
|
|
||||||
public Optional<V> getResult(K key)
|
|
||||||
{
|
|
||||||
MemoizedResult<V> result = map.get(key);
|
|
||||||
if(result != null)
|
|
||||||
{
|
|
||||||
if(result.getTime().isAfter(Instant.now().minus(timeout)))
|
|
||||||
{
|
|
||||||
return (Optional.ofNullable(result.getResult()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Get the memoized Value for a given input Key - computing it if it wasn't previously
|
** Get the memoized Value for a given input Key - computing it if it wasn't previously
|
||||||
** memoized (or expired).
|
** memoized (or expired).
|
||||||
**
|
**
|
||||||
** In here, if the optional is empty, it means the value is null (whether that
|
** If the returned Optional is empty, it means the value is null (whether that
|
||||||
** came form memoization, or from the lookupFunction, you don't care - the answer
|
** came form memoization, or from the lookupFunction, you don't care - the answer
|
||||||
** is null).
|
** is null).
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Optional<V> getResult(K key, UnsafeFunction<K, V, ?> lookupFunction)
|
public <E extends Exception> Optional<V> getResultThrowing(K key, UnsafeFunction<K, V, E> lookupFunction) throws E
|
||||||
{
|
{
|
||||||
MemoizedResult<V> result = map.get(key);
|
MemoizedResult<V> result = map.get(key);
|
||||||
if(result != null)
|
if(result != null)
|
||||||
@ -111,13 +84,34 @@ public class Memoization<K, V>
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ok - either we never memoized this key, or it's expired, so, apply the lookup function, //
|
// ok - either we never memoized this key, or it's expired, so, apply the lookup function, //
|
||||||
// store the result, and then return the value (in an Optional.ofNullable) //
|
// store the result, and then return the value (in an Optional.ofNullable) //
|
||||||
|
// and if the lookup function throws - then we let it throw. //
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
try
|
|
||||||
{
|
|
||||||
V value = lookupFunction.apply(key);
|
V value = lookupFunction.apply(key);
|
||||||
storeResult(key, value);
|
storeResult(key, value);
|
||||||
return (Optional.ofNullable(value));
|
return (Optional.ofNullable(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Get the memoized Value for a given input Key - computing it if it wasn't previously
|
||||||
|
** memoized (or expired).
|
||||||
|
**
|
||||||
|
** If a null value was memoized, the resulting optional here will be empty.
|
||||||
|
**
|
||||||
|
** If the lookup function throws, then a null value will be memoized and an empty
|
||||||
|
** Optional will be returned.
|
||||||
|
**
|
||||||
|
** In here, if the optional is empty, it means the value is null (whether that
|
||||||
|
** came form memoization, or from the lookupFunction, you don't care - the answer
|
||||||
|
** is null).
|
||||||
|
*******************************************************************************/
|
||||||
|
public Optional<V> getResult(K key, UnsafeFunction<K, V, ?> lookupFunction)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return getResultThrowing(key, lookupFunction);
|
||||||
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
LOG.warn("Uncaught Exception while executing a Memoization lookupFunction (to avoid this log, add a catch in the lookupFunction)", e);
|
LOG.warn("Uncaught Exception while executing a Memoization lookupFunction (to avoid this log, add a catch in the lookupFunction)", e);
|
||||||
@ -131,8 +125,8 @@ public class Memoization<K, V>
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Get a memoized result, optionally containing a Value, for a given input Key.
|
** Get a memoized result, optionally containing a Value, for a given input Key.
|
||||||
**
|
**
|
||||||
** In this method (contrasted with getResult), if the returned Optional is empty,
|
** If the returned Optional is empty, it means that we haven't ever looked up
|
||||||
** it means that we haven't ever looked up or memoized the key (or it's expired).
|
** or memoized the key (or it's expired).
|
||||||
**
|
**
|
||||||
** If the returned Optional is not empty, then it means we've memoized something
|
** If the returned Optional is not empty, then it means we've memoized something
|
||||||
** (and it's not expired) - so if the Value from the MemoizedResult is null,
|
** (and it's not expired) - so if the Value from the MemoizedResult is null,
|
||||||
|
@ -39,6 +39,7 @@ import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeFunction;
|
|||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
@ -61,9 +62,9 @@ class MemoizationTest extends BaseTest
|
|||||||
memoization.setMaxSize(3);
|
memoization.setMaxSize(3);
|
||||||
memoization.setTimeout(Duration.ofMillis(100));
|
memoization.setTimeout(Duration.ofMillis(100));
|
||||||
|
|
||||||
assertThat(memoization.getResult("one")).isEmpty();
|
assertThat(memoization.getMemoizedResult("one")).isEmpty();
|
||||||
memoization.storeResult("one", 1);
|
memoization.storeResult("one", 1);
|
||||||
assertThat(memoization.getResult("one")).isPresent().get().isEqualTo(1);
|
assertThat(memoization.getMemoizedResult("one")).isPresent().get().extracting("result").isEqualTo(1);
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// store 3 more results - this should force 1 out //
|
// store 3 more results - this should force 1 out //
|
||||||
@ -71,22 +72,22 @@ class MemoizationTest extends BaseTest
|
|||||||
memoization.storeResult("two", 2);
|
memoization.storeResult("two", 2);
|
||||||
memoization.storeResult("three", 3);
|
memoization.storeResult("three", 3);
|
||||||
memoization.storeResult("four", 4);
|
memoization.storeResult("four", 4);
|
||||||
assertThat(memoization.getResult("one")).isEmpty();
|
assertThat(memoization.getMemoizedResult("one")).isEmpty();
|
||||||
|
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
// make sure others are present //
|
// make sure others are present //
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
assertThat(memoization.getResult("two")).isPresent().get().isEqualTo(2);
|
assertThat(memoization.getMemoizedResult("two")).isPresent().get().extracting("result").isEqualTo(2);
|
||||||
assertThat(memoization.getResult("three")).isPresent().get().isEqualTo(3);
|
assertThat(memoization.getMemoizedResult("three")).isPresent().get().extracting("result").isEqualTo(3);
|
||||||
assertThat(memoization.getResult("four")).isPresent().get().isEqualTo(4);
|
assertThat(memoization.getMemoizedResult("four")).isPresent().get().extracting("result").isEqualTo(4);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
// wait more than the timeout, then make sure all are gone //
|
// wait more than the timeout, then make sure all are gone //
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
SleepUtils.sleep(150, TimeUnit.MILLISECONDS);
|
SleepUtils.sleep(150, TimeUnit.MILLISECONDS);
|
||||||
assertThat(memoization.getResult("two")).isEmpty();
|
assertThat(memoization.getMemoizedResult("two")).isEmpty();
|
||||||
assertThat(memoization.getResult("three")).isEmpty();
|
assertThat(memoization.getMemoizedResult("three")).isEmpty();
|
||||||
assertThat(memoization.getResult("four")).isEmpty();
|
assertThat(memoization.getMemoizedResult("four")).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -100,24 +101,17 @@ class MemoizationTest extends BaseTest
|
|||||||
Memoization<String, Integer> memoization = new Memoization<>();
|
Memoization<String, Integer> memoization = new Memoization<>();
|
||||||
memoization.storeResult("null", null);
|
memoization.storeResult("null", null);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// note - we can't tell a stored null apart from a non-stored value by calling getResult //
|
// the memoizedResult should never be null, and should be present if we memoized/stored a null value //
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
Optional<Integer> optionalNull = memoization.getResult("null");
|
|
||||||
assertNotNull(optionalNull);
|
|
||||||
assertTrue(optionalNull.isEmpty());
|
|
||||||
|
|
||||||
////////////////////////////////////////////
|
|
||||||
// instead, we must use getMemoizedResult //
|
|
||||||
////////////////////////////////////////////
|
|
||||||
Optional<MemoizedResult<Integer>> optionalMemoizedResult = memoization.getMemoizedResult("null");
|
Optional<MemoizedResult<Integer>> optionalMemoizedResult = memoization.getMemoizedResult("null");
|
||||||
assertNotNull(optionalMemoizedResult);
|
assertNotNull(optionalMemoizedResult);
|
||||||
assertTrue(optionalMemoizedResult.isPresent());
|
assertTrue(optionalMemoizedResult.isPresent());
|
||||||
assertNull(optionalMemoizedResult.get().getResult());
|
assertNull(optionalMemoizedResult.get().getResult());
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// make sure getMemoizedResult returns empty for an un-set key //
|
// make sure getMemoizedResult returns non-null and empty for an un-set key //
|
||||||
/////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
optionalMemoizedResult = memoization.getMemoizedResult("never-stored");
|
optionalMemoizedResult = memoization.getMemoizedResult("never-stored");
|
||||||
assertNotNull(optionalMemoizedResult);
|
assertNotNull(optionalMemoizedResult);
|
||||||
assertTrue(optionalMemoizedResult.isEmpty());
|
assertTrue(optionalMemoizedResult.isEmpty());
|
||||||
@ -177,6 +171,23 @@ class MemoizationTest extends BaseTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testGetResultThrowing() throws Exception
|
||||||
|
{
|
||||||
|
Memoization<String, Integer> memoization = new Memoization<>();
|
||||||
|
|
||||||
|
UnsafeFunction<String, Integer, Exception> lookupFunction = Integer::parseInt;
|
||||||
|
|
||||||
|
assertEquals(Optional.of(1), memoization.getResultThrowing("1", lookupFunction));
|
||||||
|
assertThatThrownBy(() -> memoization.getResultThrowing(null, lookupFunction)).hasMessageContaining("null");
|
||||||
|
assertThatThrownBy(() -> memoization.getResultThrowing("two", lookupFunction)).hasMessageContaining("For input string:");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -198,7 +209,7 @@ class MemoizationTest extends BaseTest
|
|||||||
for(int n = 0; n < 1_000_000; n++)
|
for(int n = 0; n < 1_000_000; n++)
|
||||||
{
|
{
|
||||||
memoization.storeResult(String.valueOf(n), n);
|
memoization.storeResult(String.valueOf(n), n);
|
||||||
memoization.getResult(String.valueOf(n));
|
memoization.getMemoizedResult(String.valueOf(n));
|
||||||
|
|
||||||
if(n % 100_000 == 0)
|
if(n % 100_000 == 0)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user