Last active
March 5, 2019 13:22
-
-
Save gdela/a56a30dc77eeebf86b457b8fd65ebb8f to your computer and use it in GitHub Desktop.
Code describing use case behind this question: https://stackoverflow.com/questions/54928516
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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