1 package com.atlassian.vcache;
2
3 import com.atlassian.marshalling.jdk.JavaSerializationMarshalling;
4
5 import javax.annotation.PostConstruct;
6 import java.time.Duration;
7 import java.util.Map;
8 import java.util.Optional;
9 import java.util.Set;
10 import java.util.concurrent.CompletionStage;
11 import java.util.function.Function;
12 import java.util.stream.Collectors;
13
14 import static com.atlassian.vcache.VCacheUtils.fold;
15
16
17
18
19 public class ExternalSample {
20 private static Long valueMapper(String key) {
21 switch (key) {
22 case "currentCount":
23 return 42L;
24 case "licensedCount":
25 return 666L;
26 default:
27 throw new IllegalArgumentException("Unknown key: " + key);
28 }
29 }
30
31 private static final Function<Set<String>, Map<String, Long>> VALUE_FACTORY = keys ->
32 keys.stream().collect(Collectors.toMap(key -> key, ExternalSample::valueMapper));
33
34 private final DirectExternalCache<Long> cache;
35
36 public ExternalSample(VCacheFactory factory) {
37 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder().
38 defaultTtl(Duration.ofSeconds(666)).
39 dataChangeRateHint(ChangeRate.HIGH_CHANGE).
40 entryCountHint(42).
41 entryGrowthRateHint(ChangeRate.LOW_CHANGE).
42 build();
43
44 cache = factory.getDirectExternalCache(
45 "mycache",
46 JavaSerializationMarshalling.pair(Long.TYPE),
47 settings);
48 }
49
50 @PostConstruct
51 void init() {
52
53 cache.put("licensedCount", 88L, PutPolicy.ADD_ONLY);
54 cache.put("currentCount", 12L, PutPolicy.ADD_ONLY).whenComplete((b, ex) -> {
55 if (ex != null) {
56
57 } else {
58
59 }
60 });
61 }
62
63 public boolean addUser() {
64 final CompletionStage<Map<String, Optional<IdentifiedValue<Long>>>> getOp =
65 cache.getBulkIdentified("currentCount", "licensedCount");
66
67 final CompletionStage<Boolean> outcome = getOp.handle((currentValues, t) -> {
68
69 if (t != null) {
70
71 return false;
72 }
73
74
75 if (!currentValues.get("currentCount").isPresent() || !currentValues.get("licensedCount").isPresent()) {
76
77 return false;
78 }
79
80
81 if (currentValues.get("currentCount").get().value() < currentValues.get("licensedCount").get().value()) {
82
83 return false;
84 }
85
86
87 final Long newCount = currentValues.get("currentCount").get().value() + 1;
88
89 CompletionStage<Boolean> replaceOp =
90 cache.replaceIf("currentCount", currentValues.get("currentCount").get().identifier(), newCount);
91
92 return fold(replaceOp,
93 success -> false,
94 failure -> false
95 );
96 });
97
98 return outcome.toCompletableFuture().join();
99 }
100
101 public Long spareLicenses() {
102 final CompletionStage<Map<String, Long>> cached = cache.getBulk(VALUE_FACTORY, "currentCount", "licensedCount");
103
104 return fold(cached,
105 m -> m.get("licensedCount") - m.get("currentCount"),
106 err -> -1L);
107 }
108 }