Skip to content

Instantly share code, notes, and snippets.

@gdela
Last active March 5, 2019 13:22
Show Gist options
  • Save gdela/a56a30dc77eeebf86b457b8fd65ebb8f to your computer and use it in GitHub Desktop.
Save gdela/a56a30dc77eeebf86b457b8fd65ebb8f to your computer and use it in GitHub Desktop.
Code describing use case behind this question: https://stackoverflow.com/questions/54928516
import com.hazelcast.config.Config;
import com.hazelcast.config.PredicateConfig;
import com.hazelcast.config.QueryCacheConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.HazelcastInstanceAware;
import com.hazelcast.core.IMap;
import com.hazelcast.core.TransactionalMap;
import com.hazelcast.map.EntryBackupProcessor;
import com.hazelcast.map.EntryProcessor;
import com.hazelcast.map.QueryCache;
import com.hazelcast.query.TruePredicate;
import com.hazelcast.transaction.TransactionContext;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import static java.math.BigDecimal.*;
public class QueryCacheDelayExample {
private HazelcastInstance instance;
private IMap<Character, BigDecimal> paramsMap;
private IMap<Long, Item> itemsMap;
public static void main(String[] args) {
new QueryCacheDelayExample().example();
}
private void example() {
// hazelcast configuration
Config config = new Config();
config.getMapConfig("params-map").addQueryCacheConfig(
new QueryCacheConfig("params-query-cache")
.setPredicateConfig(new PredicateConfig(TruePredicate.INSTANCE))
.setPopulate(true)
.setDelaySeconds(0)
);
instance = Hazelcast.newHazelcastInstance(config);
paramsMap = instance.getMap("params-map");
itemsMap = instance.getMap("items-map");
// initial state, we have some items and parameters for revaluation
paramsMap.putAll(allParamsSetTo(ZERO));
for (long itemId = 9991; itemId <= 9995; itemId++) {
itemsMap.put(itemId, new Item(itemId));
}
// simulation of request handling
while (true) {
Map<Character, BigDecimal> paramsChanges;
// first request
System.out.println("setting all params to " + ONE);
paramsChanges = allParamsSetTo(ONE);
handleRevaluationRequest(paramsChanges);
itemsMap.values().stream()
.filter(item -> !item.price.equals(ONE))
.forEach(item -> {
throw new AssertionError("item " + item + " was priced to " + item.price);
});
// second request
System.out.println("setting all params to " + TEN);
paramsChanges = allParamsSetTo(TEN);
handleRevaluationRequest(paramsChanges);
itemsMap.values().stream()
.filter(item -> !item.price.equals(TEN))
.forEach(item -> {
throw new AssertionError("item " + item + " was priced to " + item.price);
});
}
}
private void handleRevaluationRequest(Map<Character, BigDecimal> paramChanges) {
// update parameters
TransactionContext transaction = instance.newTransactionContext();
transaction.beginTransaction();
TransactionalMap<Character, BigDecimal> parameters = transaction.getMap(paramsMap.getName());
for (Entry<Character, BigDecimal> parameterChange : paramChanges.entrySet()) {
parameters.put(parameterChange.getKey(), parameterChange.getValue());
}
transaction.commitTransaction();
// revalue items
itemsMap.executeOnEntries(new RevaluationProcessor());
// processor uses new and/or existing parameters from QueryCache to revalue items
// but won't always see the changes to parameters that we've just made
}
private Map<Character, BigDecimal> allParamsSetTo(BigDecimal value) {
Map<Character, BigDecimal> params = new HashMap<>();
for (char paramKey = 'A'; paramKey < 'Z'; paramKey++) {
params.put(paramKey, value);
}
return params;
}
public static class RevaluationProcessor implements EntryProcessor<Long, Item>, EntryBackupProcessor<Long, Item>, HazelcastInstanceAware, Serializable {
private QueryCache<Character, BigDecimal> paramsQueryCache;
@Override
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
IMap<Character, BigDecimal> tariffMap = hazelcastInstance.getMap("params-map");
paramsQueryCache = tariffMap.getQueryCache("params-query-cache");
}
@Override
public Object process(Entry<Long, Item> entry) {
Item item = entry.getValue();
char paramKey = ((char) (item.id % 25 + 'A')); // matching parameters is more complicated in reality
BigDecimal paramValue = paramsQueryCache.get(paramKey);
item.price = paramValue; // calculating prices is more complicated in reality
System.out.println("- item " + item.id + ", matched tariff " + paramKey + "/" + paramValue + ", calculated price " + item.price);
entry.setValue(item);
return null;
}
@Override
public EntryBackupProcessor<Long, Item> getBackupProcessor() {
return this;
}
@Override
public void processBackup(Entry<Long, Item> entry) {
process(entry);
}
}
public static class Item implements Serializable {
private long id;
private BigDecimal price;
Item(long id) {
this.id = id;
}
public String toString() {
return String.valueOf(id);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment