Hi Community,
I’m trying to implement Cache using Atlassian’s CacheManager (Atlassian Cache - API 2.9.0 API) to cache common/global user-level settings. I have several questions around cache limits and expiration that I’d appreciate some clarification on (specific to Jira Data Center):
Specific Questions:
-
Size Limits
- Is there a maximum size limit for a cache or a cached value?
For example:- Is a total cache size like 8MB(example) enforced anywhere internally?
- Can a single cached value (e.g., a long JSON string or object) be several hundred KB or even a few MB?
- Can I safely cache thousands of user entries in a List (containing usernames)?
- Is there a maximum size limit for a cache or a cached value?
-
Expiration Policy
- Is it mandatory to set an expiration policy?
- What happens if I don’t set any expiry?
I’m considering managing the cache manually usingget()
andput()
when the DB is updated or reinitialize it on Server restart. - Are there recommended TTL values for plugin-level caching?
Sample Code:
package com.example.helloworld.cache;
import com.atlassian.cache.Cache;
import com.atlassian.cache.CacheLoader;
import com.atlassian.cache.CacheManager;
import com.atlassian.cache.CacheSettings;
import com.atlassian.cache.CacheSettingsBuilder;
import com.atlassian.sal.api.pluginsettings.PluginSettings;
import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
public class HelloWorldCacheManager {
private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldCacheManager.class);
private static final String DB_KEY_HELLO_NAME = "com.example.helloworld.HELLO_NAME";
private static final String CACHE_KEY_HELLO_NAME = "hello-name";
private final PluginSettingsFactory pluginSettingsFactory;
private final CacheManager cacheManager;
private static volatile Cache<String, String> helloNameCache;
@Inject
public HelloWorldCacheManager(PluginSettingsFactory pluginSettingsFactory, CacheManager cacheManager) {
this.pluginSettingsFactory = pluginSettingsFactory;
this.cacheManager = cacheManager;
}
/**
* Initializes the cache lazily and thread-safely.
*/
public Cache<String, String> getCache() {
if (helloNameCache == null) {
synchronized (HelloWorldCacheManager.class) {
if (helloNameCache == null) {
LOGGER.debug(">>> Initializing helloNameCache");
CacheSettings cacheSettings = new CacheSettingsBuilder()
.remote()
.replicateViaInvalidation()
.build();
helloNameCache = cacheManager.getCache(
"com.example.helloworld:name-cache",
new CacheLoader<String, String>() {
@Override
public String load(String key) {
LOGGER.debug(">>> Cache miss - Loading from DB via PluginSettings");
PluginSettings settings = pluginSettingsFactory.createGlobalSettings();
String value = (String) settings.get(DB_KEY_HELLO_NAME);
return value != null ? value : "World";
}
},
cacheSettings
);
}
}
}
return helloNameCache;
}
/**
* Retrieves the name from cache, or DB if not cached.
*/
public String getHelloName() {
Cache<String, String> cache = getCache();
String value = cache.get(CACHE_KEY_HELLO_NAME);
LOGGER.debug(">>> Retrieved 'HELLO_NAME' = {}", value);
return value;
}
/**
* Updates both the cache and DB.
*/
public void setHelloName(String value) {
PluginSettings settings = pluginSettingsFactory.createGlobalSettings();
settings.put(DB_KEY_HELLO_NAME, value);
getCache().put(CACHE_KEY_HELLO_NAME, value);
LOGGER.debug(">>> Updated 'HELLO_NAME' to value: {}", value);
}
/**
* Updates the cache only (no DB update).
*/
public void updateHelloNameCacheOnly(String value) {
getCache().put(CACHE_KEY_HELLO_NAME, value);
LOGGER.debug(">>> Updated 'HELLO_NAME' in cache only to value: {}", value);
}
/**
* Clears the cached name value.
*/
public void clearHelloNameCache() {
getCache().remove(CACHE_KEY_HELLO_NAME);
LOGGER.debug(">>> Cleared cache for 'HELLO_NAME'");
}
}
Any guidance or references to documentation would be greatly appreciated!
Thanks!