Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support in cache:create() for 'expireAfterWrite' in $config #4975

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public Cache(final CacheConfig config) {

config.getMaximumSize().map(cacheBuilder::maximumSize);
config.getExpireAfterAccess().map(ms -> cacheBuilder.expireAfterAccess(ms, TimeUnit.MILLISECONDS));
config.getExpireAfterWrite().map(ms -> cacheBuilder.expireAfterWrite(ms, TimeUnit.MILLISECONDS));

this.store = cacheBuilder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,19 @@ public class CacheConfig {
private final Optional<Permissions> permissions;
private final Optional<Long> maximumSize;
private final Optional<Long> expireAfterAccess;
private final Optional<Long> expireAfterWrite;

/**
* @param permissions Any restrictions on cache operations
* @param maximumSize The maximimum number of entries in the cache
* @param expireAfterAccess The time in milliseconds after the entry is last accessed, that it should expire
* @param expireAfterWrite The time in milliseconds after the entry is last modified, that it should expire
*/
public CacheConfig(final Optional<Permissions> permissions, final Optional<Long> maximumSize, final Optional<Long> expireAfterAccess) {
public CacheConfig(final Optional<Permissions> permissions, final Optional<Long> maximumSize, final Optional<Long> expireAfterAccess, final Optional<Long> expireAfterWrite) {
this.permissions = permissions;
this.maximumSize = maximumSize;
this.expireAfterAccess = expireAfterAccess;
this.expireAfterWrite = expireAfterWrite;
}

public Optional<Permissions> getPermissions() {
Expand All @@ -57,6 +60,10 @@ public Optional<Long> getExpireAfterAccess() {
return expireAfterAccess;
}

public Optional<Long> getExpireAfterWrite() {
return expireAfterWrite;
}

public static class Permissions {
private final Optional<String> putGroup;
private final Optional<String> getGroup;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class CacheFunctions extends BasicFunction {
"Explicitly create a cache with a specific configuration",
returns(Type.BOOLEAN, "true if the cache was created, false if the cache already exists"),
FS_PARAM_CACHE_NAME,
param("config", Type.MAP, "A map with configuration for the cache. At present cache LRU and permission groups may be specified, for operations on the cache. `maximumSize` is optional and specifies the maximum number of entries. `expireAfterAccess` is optional and specifies the expiry period for infrequently accessed entries (in milliseconds). If a permission group is not specified for an operation, then permissions are not checked for that operation. Should have the format: map { \"maximumSize\": 1000, \"expireAfterAccess\": 120000, \"permissions\": map { \"put-group\": \"group1\", \"get-group\": \"group2\", \"remove-group\": \"group3\", \"clear-group\": \"group4\"} }")
param("config", Type.MAP, "A map with configuration for the cache. At present cache LRU and permission groups may be specified, for operations on the cache. `maximumSize` is optional and specifies the maximum number of entries. `expireAfterAccess` is optional and specifies the expiry period for infrequently accessed entries (in milliseconds). `expireAfterWrite` is optional and specifies the expiry period after the entry's creation, or the most recent replacement of its value (in milliseconds). If a permission group is not specified for an operation, then permissions are not checked for that operation. Should have the format: map { \"maximumSize\": 1000, \"expireAfterAccess\": 120000, \"expireAfterWrite\": 240000, \"permissions\": map { \"put-group\": \"group1\", \"get-group\": \"group2\", \"remove-group\": \"group3\", \"clear-group\": \"group4\"} }")
);

private static final String FS_NAMES_NAME = "names";
Expand Down Expand Up @@ -277,7 +277,16 @@ private CacheConfig extractCacheConfig(final MapType configMap) throws XPathExce
expireAfterAccess = Optional.empty();
}

return new CacheConfig(permissions, maximumSize, expireAfterAccess);
final Sequence expireAfterWriteSeq = configMap.get(new StringValue(this, "expireAfterWrite"));
final Optional<Long> expireAfterWrite;
if(expireAfterWriteSeq != null && expireAfterWriteSeq.getItemCount() == 1) {
final long l = expireAfterWriteSeq.itemAt(0).toJavaObject(Long.class);
expireAfterWrite = Optional.of(l);
} else {
expireAfterWrite = Optional.empty();
}

return new CacheConfig(permissions, maximumSize, expireAfterAccess, expireAfterWrite);
}

private Optional<String> getStringValue(final String key, final AbstractMapType map) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,15 @@ public class CacheModule extends AbstractInternalModule {
private static final String PARAM_NAME_ENABLE_LAZY_CREATION = "enableLazyCreation";
private static final String PARAM_NAME_LAZY_MAXIMUM_SIZE = "lazy.maximumSize";
private static final String PARAM_NAME_LAZY_EXPIRE_AFTER_ACCESS = "lazy.expireAfterAccess";
private static final String PARAM_NAME_LAZY_EXPIRE_AFTER_WRITE = "lazy.expireAfterWrite";
private static final String PARAM_NAME_LAZY_PUT_GROUP = "lazy.putGroup";
private static final String PARAM_NAME_LAZY_GET_GROUP = "lazy.getGroup";
private static final String PARAM_NAME_LAZY_REMOVE_GROUP = "lazy.removeGroup";
private static final String PARAM_NAME_LAZY_CLEAR_GROUP = "lazy.clearGroup";

private static final long DEFAULT_LAZY_MAXIMUM_SIZE = 128; // 128 items
private static final long DEFAULT_LAZY_EXPIRE_AFTER_ACCESS = 1000 * 60 * 5; // 5 minutes
private static final long DEFAULT_LAZY_EXPIRE_AFTER_WRITE = 1000 * 60 * 5; // 5 minutes

static final Map<String, Cache> caches = new ConcurrentHashMap<>();

Expand Down Expand Up @@ -167,8 +169,18 @@ private static Optional<CacheConfig> parseParameters(final Map<String, List<?>>
}
});

final Optional<Long> expireAfterWrite = getFirstString(parameters, PARAM_NAME_LAZY_EXPIRE_AFTER_WRITE)
.map(s -> {
try {
return Long.parseLong(s);
} catch (final NumberFormatException e) {
LOG.warn("Unable to set {} to: {}. Using default: ", PARAM_NAME_LAZY_EXPIRE_AFTER_WRITE, s, DEFAULT_LAZY_EXPIRE_AFTER_WRITE);
return DEFAULT_LAZY_EXPIRE_AFTER_ACCESS;
}
});


return Optional.of(new CacheConfig(permissions, maximumSize, expireAfterAccess));
return Optional.of(new CacheConfig(permissions, maximumSize, expireAfterAccess, expireAfterWrite));
}

private static Optional<String> getFirstString(final Map<String, List<?>> parameters, final String paramName) {
Expand Down
21 changes: 21 additions & 0 deletions extensions/modules/cache/src/test/xquery/modules/cache/cache.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ declare variable $c:maximumSize := 5;
declare variable $c:maximumSize-options := map { "maximumSize": $c:maximumSize };
declare variable $c:expireAfterAccess := 1000;
declare variable $c:expireAfterAccess-options := map { "expireAfterAccess": $c:expireAfterAccess };
declare variable $c:expireAfterWrite := 1000;
declare variable $c:expireAfterWrite-options := map { "expireAfterWrite": $c:expireAfterWrite };

declare function c:_create-simple() {
cache:create($c:cache-name, $c:simple-options)
Expand All @@ -46,6 +48,10 @@ declare function c:_create-expireAfterAccess() {
cache:create($c:cache-name, $c:expireAfterAccess-options)
};

declare function c:_create-expireAfterWrite() {
cache:create($c:cache-name, $c:expireAfterWrite-options)
};

declare function c:_populate($size as xs:integer) {
(1 to $size) ! cache:put($c:cache-name, "foo" || ., "bar" || .)
};
Expand Down Expand Up @@ -171,6 +177,21 @@ function c:exercise-expireAfterAccess() {
count(c:_keys())
};

declare
%test:assertEquals(0)
function c:exercise-expireAfterWrite() {
let $setup :=
(
c:_destroy(),
c:_create-expireAfterWrite(),
c:_populate(5),
util:wait($c:expireAfterWrite * 1.1),
c:_cleanup()
)
return
count(c:_keys())
};

declare
%test:assertEquals("bar5")
function c:get() {
Expand Down
Loading