Skip to content

Commit

Permalink
Added ageing capabilities to SessionCache and NullCache
Browse files Browse the repository at this point in the history
Added ageing methods to the Cache Adaptor interface so it's now universal
  • Loading branch information
rob-baillie-ortoo committed Apr 26, 2022
1 parent 14fc597 commit e8d1113
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 8 deletions.
4 changes: 1 addition & 3 deletions TODO.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
TODO:
* Combine the DateTimeUtils and DateLiterals where appropriate
* Document TestDateTimeUtils and how to set now and today
* Test ageing using dates on the OrgCache
* Implement ageing into the SessionCache
* Add the aged get definitions into ICacheAdaptor
* Add 'maximum age' into CachedSoqlExecutor
* Consider a superclass for OrgCache and SessionCache?



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public interface ICacheAdaptor
Boolean hasAccessToCache();
Boolean isACache();
Object get( String key );
Object get( String key, DateTime minimumDateTime );
Object get( String key, Long maximumAgeInSeconds );
void put( String key, Object value, Integer lifespan );
Boolean contains( String key );
void remove( String key );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ public inherited sharing class NullCache implements ICacheAdaptor
return null;
}

public Object get( String key, DateTime minimumDateTime )
{
return null;
}

public Object get( String key, Long maximumAgeInSeconds )
{
return null;
}

public Set<String> getKeys()
{
return new Set<String>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*
* All users are assumed to have access to the cache.
*/
// TODO: add age capabilities
public inherited sharing class SessionCache implements ICacheAdaptor
{
private static final String PARTITION_NAME = 'core';
Expand Down Expand Up @@ -35,9 +34,58 @@ public inherited sharing class SessionCache implements ICacheAdaptor
* @return Object The cached object, if it exists
*/
public Object get( String key )
{
Long maximumAgeInSeconds = null;
return get( key, maximumAgeInSeconds );
}

/**
* Retrieve the cache entry with the given key, but only if it was created after the stated date time
*
* If the entry does not exist in the cache (I.E. is a "cache miss"), will return null
*
* @param String The key for the object to retrieve
* @return Object The cached object, if it exists
*/
public Object get( String key, DateTime minimumDateTime )
{
Long maximumAgeInSeconds;
if ( minimumDateTime != null )
{
maximumAgeInSeconds = DateTimeUtils.getEpochTime() - DateTimeUtils.getEpochTime( minimumDateTime );
}
return get( key, maximumAgeInSeconds );
}

/**
* Retrieve the cache entry with the given key, but only if it is younger than the stated number of seconds
*
* If the entry does not exist in the cache (I.E. is a "cache miss"), will return null
*
* @param String The key for the object to retrieve
* @return Object The cached object, if it exists
*/
public Object get( String key, Long maximumAgeInSeconds )
{
Contract.requires( String.isNotBlank( key ), 'get called with a blank key' );
return Cache.Session.get( key );

Object rawCacheValue = Cache.Session.get( createFullyQualifiedKey( key ) );

if ( rawCacheValue instanceOf CacheEntry )
{
CacheEntry cacheValue = (CacheEntry)rawCacheValue;
if ( maximumAgeInSeconds == null || cacheValue.isYoungerThanOrEqualTo( maximumAgeInSeconds ) )
{
return cacheValue.getValue();
}
}

if ( maximumAgeInSeconds == null ) // if we don't care about the age, then return it
{
return rawCacheValue;
}

return null; // if there is no age, or it is too old, regard it as a cache miss
}

/**
Expand Down Expand Up @@ -66,7 +114,9 @@ public inherited sharing class SessionCache implements ICacheAdaptor
Contract.requires( lifespan >= 0, 'put called with a negative lifespan' );
// Note that the maximum is handled by Salesforce, just in case it increases

Cache.Session.put( key, value, lifespan, Cache.Visibility.NAMESPACE, true ); // immutable outside of namespace
CacheEntry cacheEntry = new CacheEntry( value );

Cache.Session.put( key, cacheEntry, lifespan, Cache.Visibility.NAMESPACE, true ); // immutable outside of namespace
}

/**
Expand Down Expand Up @@ -112,6 +162,7 @@ public inherited sharing class SessionCache implements ICacheAdaptor
return Cache.SessionPartition.createFullyQualifiedPartition( PackageUtils.NAMESPACE_PREFIX, PARTITION_NAME );
}

@testVisible
private String createFullyQualifiedKey( String key )
{
return Cache.SessionPartition.createFullyQualifiedKey( PackageUtils.NAMESPACE_PREFIX, PARTITION_NAME, key );
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
@isTest
private without sharing class NullCacheTest
{
private final static Long NULL_AGE = null;
private final static DateTime NULL_MIN_DATE_TIME = null;

@isTest
private static void hasAccessToCache_whenCalled_returnsTrue() // NOPMD: Test method name format
{
Expand All @@ -25,6 +28,22 @@ private without sharing class NullCacheTest
System.assertEquals( null, got, 'get, when called, will return null' );
}

@isTest
private static void get_maxAge_whenCalled_returnsNull() // NOPMD: Test method name format
{
NullCache cache = new NullCache();
Object got = cache.get( null, NULL_AGE );
System.assertEquals( null, got, 'get, when called with a max age, will return null' );
}

@isTest
private static void get_minDate_whenCalled_returnsNull() // NOPMD: Test method name format
{
NullCache cache = new NullCache();
Object got = cache.get( null, NULL_MIN_DATE_TIME );
System.assertEquals( null, got, 'get, when called with a min datetime, will return null' );
}

@isTest
private static void put_whenCalled_doesNothing() // NOPMD: Test method name format
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ private without sharing class OrgCacheTest
private final static Integer DEFAULT_LIFESPAN = 1000;
private final static DateTime BASE_TIME = DateTime.newInstanceGmt( 1974, 08, 24, 22, 45, 00 );
private final static Long NULL_AGE = null;
private final static DateTime NULL_MAX_DATE_TIME = null;
private final static DateTime NULL_MIN_DATE_TIME = null;

@isTest
private static void hasAccessToCache_whenCalledByUserWithCacheAccess_returnsTrue() // NOPMD: Test method name format
Expand Down Expand Up @@ -314,7 +314,7 @@ private without sharing class OrgCacheTest
Cache.Org.put( cacheInstance.createFullyQualifiedKey( 'key' ), cachedObject );

Test.startTest();
Object got = cacheInstance.get( 'key', NULL_MAX_DATE_TIME );
Object got = cacheInstance.get( 'key', NULL_MIN_DATE_TIME );
Test.stopTest();

System.assertEquals( cachedObject, got, 'get, passing minimumDateTime, when no time is specified and the cached value has no age, will return the value' );
Expand Down
Loading

0 comments on commit e8d1113

Please sign in to comment.