There is no explicit way to change the default expiry policy of a Cache
(either in JCache or
Hazelcast-specific APIs).
You can achieve the same effect by configuring your Cache
with a custom Factory<ExpiryPolicy>
.
In your ExpiryPolicy
implementation you can consult your external service to query the current
expiry duration and return that so the JCache implementation applies it. Notice that since the expiry policy
is queried on each entry creation/access/update, it is best that ExpiryPolicy
methods implementation do not involve
any remote service queries or database access, otherwise you will experience high latency. For example,
it is best to register your expiry policy as a listener to your external service (if supported)
or have a separate executor to schedule queries to the external service for updates.
Example implementation using JCache API:
class Scratch {
public static void main(String[] args)
throws InterruptedException {
MutableConfiguration<String, String[]> roleCacheConfig = new MutableConfiguration<>();
// other config here...
roleCacheConfig.setExpiryPolicyFactory(new CustomExpiryPolicyFactory());
CachingProvider provider = Caching.getCachingProvider();
CacheManager manager = provider.getCacheManager();
Cache<String, String[]> cache = manager.createCache("test", roleCacheConfig);
cache.put("a", new String[]{}); // consults getExpiryForCreation
Thread.sleep(1000);
cache.get("a"); // consults getExpiryForAccess
Thread.sleep(1000);
cache.put("a", new String[]{}); // consults getExpiryForUpdate
}
public static class CustomExpiryPolicyFactory implements Factory<ExpiryPolicy>, Serializable {
@Override
public ExpiryPolicy create() {
// initialize custom expiry policy: at this point
// the custom expiry policy should be registered as listener to
// external service publishing expiry info or otherwise configured
// to poll the external service for new expiry info
CustomExpiryPolicy expiryPolicy = new CustomExpiryPolicy(120, 30, 120);
return expiryPolicy;
}
}
public static class CustomExpiryPolicy implements ExpiryPolicy {
private volatile Duration expiryForCreation;
private volatile Duration expiryForAccess;
private volatile Duration expiryForUpdate;
public CustomExpiryPolicy(long secondsForCreation,
long secondsForAccess,
long secondsForUpdate) {
this.expiryForCreation = new Duration(TimeUnit.SECONDS, secondsForCreation);
this.expiryForAccess = new Duration(TimeUnit.SECONDS, secondsForAccess);
this.expiryForUpdate = new Duration(TimeUnit.SECONDS, secondsForUpdate);
}
// assuming this is invoked from external service whenever there is a change
public void onExpiryChanged(long secondsForCreation,
long secondsForAccess,
long secondsForUpdate) {
this.expiryForCreation = new Duration(TimeUnit.SECONDS, secondsForCreation);
this.expiryForAccess = new Duration(TimeUnit.SECONDS, secondsForAccess);
this.expiryForUpdate = new Duration(TimeUnit.SECONDS, secondsForUpdate);
}
@Override
public Duration getExpiryForCreation() {
return expiryForCreation;
}
@Override
public Duration getExpiryForAccess() {
return expiryForAccess;
}
@Override
public Duration getExpiryForUpdate() {
return expiryForUpdate;
}
}
}
You can supply your custom expiry policy factory class name in declarative Hazelcast XML config like this:
<cache name="toto">
<async-backup-count>1</async-backup-count>
<backup-count>1</backup-count>
...
<expiry-policy-factory class-name="com.example.cache.CustomExpirePolicyFactory" />
...
</cache>
As a side-note, there are methods in ICache
, the Hazelcast-specific extended Cache
interface, that allow
you to perform operations on a key or set of keys with a custom expiry policy specified per-key (but not change the cache-wide applicable expiry policy).