Object cache
Cache concept
The cache plugin is intended to obtain an object from the global server cache by a key or store an object in the cache for future requests. The plugin body is executed only when the key cannot be found in the cache.
Otherwise, the last executed result is returned.
Mind the following cache features:
- The current implementation uses a single cache shared inside JVM (the WorkFusion application).
- The cache is shared between all users, but its element lifetime is limited to ten mins by default.
- The maximum cache size is 50 elements, and a new cache key deletes the oldest one.
Usage example: You run a Business Process with multiple records. All these records have the same response to be emailed only once, with the first record passing this Bot Task.
For more details on the cache plugin, refer to Bot Task plugins | cache.
ODF 2 and cache
Let's look at the essential cache behavior in a code. Assume you have heavy resource-consuming calculations that do not depend on real-time data. The result of this calculation is the same during hours.
In this case, you can leverage the pool pattern and test-call complexCalculation multiple times via the cache. In a real Business Process, continuous multi-record execution of complexCalculation is run only once every ten minutes:
private int calculationsCount = 0;
private void testCache(CacheService cacheService) {
final String cacheKey = "complexCalculationResult";
final String firstResult = cacheService.get(cacheKey, this::complexCalculation);
final String secondResult = cacheService.get(cacheKey, this::complexCalculation);
assert firstResult.equals("result"); // both calculations must give the SAME result
assert secondResult.equals("result"); // both calculations must give the SAME result
assert calculationsCount == 1; // but the cache supplier's method must be executed ONLY ONCE within a 10-minute timeframe
}
private String complexCalculation() {
calculationsCount++;
return "result";
}
Every ODF 2 Bot Task uses the pre-defined WebHarvestServicesModule module instantiated at the entry point for the whole framework. It is called from the generated Bot Task code where the platform service wrappers are provided as injectables.
Among other useful services, the module provides CacheService you can use to build the cache. For that, inject CacheService into your Bot Task constructor:
@BotTask
public class CachePluginTask implements GenericTask {
private final CacheService cacheService;
private final BindingReader bindingReader;
private final TaskOutput taskOutput;
@Inject
public CachePluginTask(CacheService cacheService, BindingReader bindingReader, TaskOutput taskOutput) {
this.cacheService = cacheService;
this.bindingReader = bindingReader;
this.taskOutput = taskOutput;
}
@Override
public void run() {
String cacheKey = getVariable("cache-key");
List<String> supplierResult = getVariableAsList("supplier-result");
List<String> cachePluginResult = cacheService.get(cacheKey, () -> supplierResult);
cacheService.get(cacheKey, () -> {
throw new IllegalStateException("This exception must never be thrown");
});
taskOutput.setColumn("cache-plugin-result", cachePluginResult.toString());
}
private String getVariable(String name) {
return bindingReader.getRequiredVariable(name, String.class);
}
private List<String> getVariableAsList(String name) {
return Arrays.asList(getVariable(name).split(","));
}
}