1 package com.atlassian.vcache.internal.test;
2
3 import com.atlassian.marshalling.api.MarshallingPair;
4 import com.atlassian.marshalling.jdk.StringMarshalling;
5 import com.atlassian.vcache.ChangeRate;
6 import com.atlassian.vcache.DirectExternalCache;
7 import com.atlassian.vcache.ExternalCacheException;
8 import com.atlassian.vcache.ExternalCacheSettings;
9 import com.atlassian.vcache.ExternalCacheSettingsBuilder;
10 import com.atlassian.vcache.JvmCache;
11 import com.atlassian.vcache.JvmCacheSettings;
12 import com.atlassian.vcache.JvmCacheSettingsBuilder;
13 import com.atlassian.vcache.RequestCache;
14 import com.atlassian.vcache.StableReadExternalCache;
15 import com.atlassian.vcache.TransactionalExternalCache;
16 import com.atlassian.vcache.VCacheFactory;
17 import com.atlassian.vcache.VCacheUtils;
18 import com.atlassian.vcache.internal.BegunTransactionalActivityHandler;
19 import com.atlassian.vcache.internal.ExternalCacheDetails;
20 import com.atlassian.vcache.internal.JvmCacheDetails;
21 import com.atlassian.vcache.internal.LongMetric;
22 import com.atlassian.vcache.internal.MetricLabel;
23 import com.atlassian.vcache.internal.RequestCacheDetails;
24 import com.atlassian.vcache.internal.RequestContext;
25 import com.atlassian.vcache.internal.RequestMetrics;
26 import com.atlassian.vcache.internal.VCacheLifecycleManager;
27 import com.atlassian.vcache.internal.VCacheManagement;
28 import com.atlassian.vcache.marshallers.MarshallerFactory;
29 import org.junit.Ignore;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.rules.ExpectedException;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import java.time.Duration;
37 import java.util.EnumMap;
38 import java.util.Map;
39 import java.util.Optional;
40 import java.util.concurrent.CompletionStage;
41
42 import static com.atlassian.vcache.PutPolicy.PUT_ALWAYS;
43 import static com.atlassian.vcache.VCacheUtils.unsafeJoin;
44 import static com.atlassian.vcache.internal.test.CompletionStageSuccessful.successful;
45 import static com.atlassian.vcache.internal.test.CompletionStageSuccessful.successfulWith;
46 import static org.hamcrest.CoreMatchers.not;
47 import static org.hamcrest.Matchers.containsInAnyOrder;
48 import static org.hamcrest.Matchers.greaterThan;
49 import static org.hamcrest.Matchers.is;
50 import static org.hamcrest.Matchers.notNullValue;
51 import static org.junit.Assert.assertThat;
52
53
54
55
56 @SuppressWarnings("OptionalGetWithoutIsPresent")
57 public abstract class AbstractVCacheServiceIT {
58 protected static final int MAX_ENTRIES = 100;
59 protected static final Duration MAX_TTL = Duration.ofSeconds(60);
60
61 private static final Logger log = LoggerFactory.getLogger(AbstractVCacheServiceIT.class);
62
63 @Rule
64 public ExpectedException thrown = ExpectedException.none();
65
66 @Rule
67 public LoggingTestWatcher watcher = new LoggingTestWatcher(log);
68
69 @SuppressWarnings("WeakerAccess")
70 protected int invocationsOfBegunTxns;
71 protected final BegunTransactionalActivityHandler begunTxnActivityHandler = c -> invocationsOfBegunTxns++;
72
73 protected abstract VCacheFactory vCacheFactory();
74
75 protected abstract VCacheManagement vCacheManagement();
76
77 protected abstract VCacheLifecycleManager vCacheLifecycleManager();
78
79 protected abstract RequestContext currentRequestContext();
80
81 protected abstract void forceNewRequestContext();
82
83 @Test
84 public void jvmCache_normal() {
85 final JvmCacheSettings settings = new JvmCacheSettingsBuilder()
86 .defaultTtl(MAX_TTL.plusSeconds(1))
87 .maxEntries(MAX_ENTRIES + 1)
88 .build();
89
90 final JvmCache<String, Long> cache = vCacheFactory().getJvmCache("my-jvm-cache", settings);
91
92 assertThat(cache, notNullValue());
93 assertThat(cache.getName(), is("my-jvm-cache"));
94
95 cache.put("key", 666L);
96
97 final RequestMetrics metrics = vCacheLifecycleManager().metrics(currentRequestContext());
98
99 assertThat(metrics, notNullValue());
100 assertThat(metrics.allJvmCacheLongMetrics(), notNullValue());
101
102 final EnumMap<MetricLabel, ? extends LongMetric> myCacheMetrics =
103 metrics.allJvmCacheLongMetrics().get("my-jvm-cache");
104
105 assertThat(myCacheMetrics, notNullValue());
106 final LongMetric timedPuts = myCacheMetrics.get(MetricLabel.TIMED_PUT_CALL);
107 assertThat(timedPuts, notNullValue());
108 assertThat(timedPuts.getSampleCount(), is(1L));
109 assertThat(timedPuts.getSamplesTotal(), greaterThan(0L));
110 assertThat(vCacheManagement().allExternalCacheDetails().size(), is(0));
111 assertThat(vCacheManagement().allRequestCacheDetails().size(), is(0));
112
113 final Map<String, JvmCacheDetails> allCacheDetails = vCacheManagement().allJvmCacheDetails();
114
115 assertThat(allCacheDetails, notNullValue());
116 assertThat(allCacheDetails.keySet(), containsInAnyOrder("my-jvm-cache"));
117
118 final JvmCacheDetails cacheDetails = allCacheDetails.get("my-jvm-cache");
119
120 assertThat(cacheDetails.getName(), is("my-jvm-cache"));
121 assertThat(cacheDetails.getSettings().getDefaultTtl(), is(Optional.of(MAX_TTL)));
122 assertThat(cacheDetails.getSettings().getMaxEntries(), is(Optional.of(MAX_ENTRIES)));
123
124 assertThat(invocationsOfBegunTxns, is(0));
125 }
126
127 @Test
128 public void requestCache_normal() {
129 final RequestCache<String, String> cache = vCacheFactory().getRequestCache("my-request-cache");
130
131 assertThat(cache, notNullValue());
132 assertThat(cache.getName(), is("my-request-cache"));
133
134 cache.removeAll();
135 cache.put("one", "eine");
136
137 final Optional<String> get1 = cache.get("one");
138
139 assertThat(get1, is(Optional.of("eine")));
140 assertThat(vCacheManagement().allJvmCacheDetails().size(), is(0));
141 assertThat(vCacheManagement().allExternalCacheDetails().size(), is(0));
142
143 final Map<String, RequestCacheDetails> allCacheDetails = vCacheManagement().allRequestCacheDetails();
144
145 assertThat(allCacheDetails, notNullValue());
146 assertThat(allCacheDetails.keySet(), containsInAnyOrder("my-request-cache"));
147
148 final RequestCacheDetails cacheDetails = allCacheDetails.get("my-request-cache");
149
150 assertThat(cacheDetails.getName(), is("my-request-cache"));
151 assertThat(invocationsOfBegunTxns, is(0));
152 }
153
154 @Test
155 public void directExternalCache_normal_marshalling() {
156 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
157 .defaultTtl(Duration.ofSeconds(60))
158 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
159 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
160 .entryCountHint(100)
161 .build();
162
163 final DirectExternalCache<String> cache = vCacheFactory().getDirectExternalCache(
164 "my-direct-cache", StringMarshalling.pair(), settings);
165
166 assertThat(cache, notNullValue());
167 assertThat(cache.getName(), is("my-direct-cache"));
168
169 final CompletionStage<Void> rmall = cache.removeAll();
170
171 assertThat(rmall, successful());
172
173 final CompletionStage<Boolean> put1 = cache.put("one", "eine", PUT_ALWAYS);
174
175 assertThat(put1, successfulWith(is(true)));
176
177 final CompletionStage<Optional<String>> get1 = cache.get("one");
178
179 assertThat(get1, successfulWith(is(Optional.of("eine"))));
180 assertThat(vCacheManagement().allJvmCacheDetails().size(), is(0));
181 assertThat(vCacheManagement().allRequestCacheDetails().size(), is(0));
182
183 final Map<String, ExternalCacheDetails> allCacheDetails = vCacheManagement().allExternalCacheDetails();
184
185 assertThat(allCacheDetails, notNullValue());
186 assertThat(allCacheDetails.keySet(), containsInAnyOrder("my-direct-cache"));
187
188 final ExternalCacheDetails cacheDetails = allCacheDetails.get("my-direct-cache");
189
190 assertThat(cacheDetails.getName(), is("my-direct-cache"));
191 assertThat(cacheDetails.getSettings().getDefaultTtl(), is(Optional.of(MAX_TTL)));
192 assertThat(cacheDetails.getSettings().getEntryCountHint(), is(Optional.of(MAX_ENTRIES)));
193 assertThat(invocationsOfBegunTxns, is(0));
194 }
195
196 @Test
197 public void directExternalCache_normal_marshaller() {
198 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
199 .defaultTtl(Duration.ofSeconds(60))
200 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
201 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
202 .entryCountHint(100)
203 .build();
204
205 @SuppressWarnings("deprecation")
206 final DirectExternalCache<String> cache = vCacheFactory().getDirectExternalCache(
207 "my-direct-cache", MarshallerFactory.stringMarshaller(), settings);
208
209 assertThat(cache, notNullValue());
210 assertThat(cache.getName(), is("my-direct-cache"));
211
212 final CompletionStage<Void> rmall = cache.removeAll();
213
214 assertThat(rmall, successful());
215
216 final CompletionStage<Boolean> put1 = cache.put("one1", "eine", PUT_ALWAYS);
217
218 assertThat(put1, successfulWith(is(true)));
219
220 final CompletionStage<Optional<String>> get1 = cache.get("one1");
221
222 assertThat(get1, successfulWith(is(Optional.of("eine"))));
223 assertThat(vCacheManagement().allJvmCacheDetails().size(), is(0));
224 assertThat(vCacheManagement().allRequestCacheDetails().size(), is(0));
225 }
226
227 @Test
228 public void stableReadExternalCache_normal_marshalling() {
229 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
230 .defaultTtl(Duration.ofSeconds(60))
231 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
232 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
233 .entryCountHint(100)
234 .build();
235
236 final StableReadExternalCache<String> cache = vCacheFactory().getStableReadExternalCache(
237 "my-stable-read-cache", StringMarshalling.pair(), settings);
238
239 assertThat(cache, notNullValue());
240 assertThat(cache.getName(), is("my-stable-read-cache"));
241
242 final CompletionStage<Void> rmall = cache.removeAll();
243
244 assertThat(rmall, successful());
245
246 final CompletionStage<Boolean> put1 = cache.put("three", "drei", PUT_ALWAYS);
247
248 assertThat(put1, successfulWith(is(true)));
249
250 final CompletionStage<Optional<String>> get1 = cache.get("three");
251
252 assertThat(get1, successfulWith(is(Optional.of("drei"))));
253 assertThat(invocationsOfBegunTxns, is(0));
254 }
255
256 @Test
257 public void stableReadExternalCache_normal_marshaller() {
258 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
259 .defaultTtl(Duration.ofSeconds(60))
260 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
261 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
262 .entryCountHint(100)
263 .build();
264
265 @SuppressWarnings("deprecation")
266 final StableReadExternalCache<String> cache = vCacheFactory().getStableReadExternalCache(
267 "my-stable-read-cache", MarshallerFactory.stringMarshaller(), settings);
268
269 assertThat(cache, notNullValue());
270 assertThat(cache.getName(), is("my-stable-read-cache"));
271
272 final CompletionStage<Void> rmall = cache.removeAll();
273
274 assertThat(rmall, successful());
275
276 final CompletionStage<Boolean> put1 = cache.put("three", "drei", PUT_ALWAYS);
277
278 assertThat(put1, successfulWith(is(true)));
279
280 final CompletionStage<Optional<String>> get1 = cache.get("three");
281
282 assertThat(get1, successfulWith(is(Optional.of("drei"))));
283 assertThat(invocationsOfBegunTxns, is(0));
284 }
285
286 @Test
287 public void transactionalExternalCache_normal_marshalling() {
288 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
289 .defaultTtl(Duration.ofSeconds(60))
290 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
291 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
292 .entryCountHint(100)
293 .build();
294
295 final TransactionalExternalCache<String> cache = vCacheFactory().getTransactionalExternalCache(
296 "my-txn-cache", StringMarshalling.pair(), settings);
297
298 assertThat(cache, notNullValue());
299 assertThat(cache.getName(), is("my-txn-cache"));
300 assertThat(invocationsOfBegunTxns, is(0));
301
302 cache.removeAll();
303 assertThat(invocationsOfBegunTxns, is(1));
304
305 cache.put("three", "drei", PUT_ALWAYS);
306
307 final CompletionStage<Optional<String>> get1 = cache.get("three");
308
309 assertThat(get1, successfulWith(is(Optional.of("drei"))));
310
311 vCacheLifecycleManager().transactionSync(currentRequestContext());
312 assertThat(invocationsOfBegunTxns, is(1));
313
314 forceNewRequestContext();
315 final CompletionStage<Optional<String>> get2 = cache.get("three");
316 assertThat(invocationsOfBegunTxns, is(2));
317 unsafeJoin(get2.toCompletableFuture()).get();
318 assertThat(get2, successfulWith(is(Optional.of("drei"))));
319 assertThat(invocationsOfBegunTxns, is(2));
320 }
321
322 @Test
323 public void transactionalExternalCache_normal_marshaller() {
324 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
325 .defaultTtl(Duration.ofSeconds(60))
326 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
327 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
328 .entryCountHint(100)
329 .build();
330
331 @SuppressWarnings("deprecation")
332 final TransactionalExternalCache<String> cache = vCacheFactory().getTransactionalExternalCache(
333 "my-txn-cache", MarshallerFactory.stringMarshaller(), settings);
334
335 assertThat(cache, notNullValue());
336 assertThat(cache.getName(), is("my-txn-cache"));
337 assertThat(invocationsOfBegunTxns, is(0));
338
339 cache.removeAll();
340 assertThat(invocationsOfBegunTxns, is(1));
341
342 cache.put("three", "drei", PUT_ALWAYS);
343
344 final CompletionStage<Optional<String>> get1 = cache.get("three");
345
346 assertThat(get1, successfulWith(is(Optional.of("drei"))));
347
348 vCacheLifecycleManager().transactionSync(currentRequestContext());
349 assertThat(invocationsOfBegunTxns, is(1));
350
351 forceNewRequestContext();
352 final CompletionStage<Optional<String>> get2 = cache.get("three");
353 assertThat(invocationsOfBegunTxns, is(2));
354 unsafeJoin(get2.toCompletableFuture()).get();
355 assertThat(get2, successfulWith(is(Optional.of("drei"))));
356 assertThat(invocationsOfBegunTxns, is(2));
357 }
358
359 @Test
360 public void verify_txns_sync_sync_sync() {
361 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
362 .defaultTtl(Duration.ofSeconds(60))
363 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
364 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
365 .entryCountHint(100)
366 .build();
367
368 final TransactionalExternalCache<String> cache1 = vCacheFactory().getTransactionalExternalCache(
369 "sync_sync_sync-1", StringMarshalling.pair(), settings);
370 assertThat(invocationsOfBegunTxns, is(0));
371
372 cache1.put("updated-key", "first1", PUT_ALWAYS);
373 assertThat(invocationsOfBegunTxns, is(1));
374
375 cache1.put("phase-1", "first", PUT_ALWAYS);
376 vCacheLifecycleManager().transactionSync(currentRequestContext());
377 assertThat(invocationsOfBegunTxns, is(1));
378
379 final TransactionalExternalCache<String> cache2 = vCacheFactory().getTransactionalExternalCache(
380 "sync_sync_sync-2", StringMarshalling.pair(), settings);
381
382 cache1.put("updated-key", "second1", PUT_ALWAYS);
383 assertThat(invocationsOfBegunTxns, is(2));
384
385 cache2.put("updated-key", "second2", PUT_ALWAYS);
386 cache1.put("phase-2", "second", PUT_ALWAYS);
387 cache2.put("phase-2", "second", PUT_ALWAYS);
388
389 vCacheLifecycleManager().transactionSync(currentRequestContext());
390 assertThat(invocationsOfBegunTxns, is(2));
391
392 final TransactionalExternalCache<String> cache3 = vCacheFactory().getTransactionalExternalCache(
393 "sync_sync_sync-3", StringMarshalling.pair(), settings);
394
395 cache1.put("updated-key", "third1", PUT_ALWAYS);
396 assertThat(invocationsOfBegunTxns, is(3));
397 cache2.put("updated-key", "third2", PUT_ALWAYS);
398 cache1.put("phase-3", "third", PUT_ALWAYS);
399 cache2.put("phase-3", "third", PUT_ALWAYS);
400 cache3.put("phase-3", "third", PUT_ALWAYS);
401
402 vCacheLifecycleManager().transactionSync(currentRequestContext());
403 assertThat(invocationsOfBegunTxns, is(3));
404
405 forceNewRequestContext();
406
407 assertThat(cache1.get("updated-key"), successfulWith(is(Optional.of("third1"))));
408 assertThat(invocationsOfBegunTxns, is(4));
409 assertThat(unsafeJoin(cache1.get("updated-key")), is(Optional.of("third1")));
410 assertThat(unsafeJoin(cache1.get("phase-1")), is(Optional.of("first")));
411 assertThat(unsafeJoin(cache1.get("phase-2")), is(Optional.of("second")));
412 assertThat(unsafeJoin(cache1.get("phase-3")), is(Optional.of("third")));
413
414 assertThat(unsafeJoin(cache2.get("updated-key")), is(Optional.of("third2")));
415 assertThat(unsafeJoin(cache2.get("phase-2")), is(Optional.of("second")));
416 assertThat(unsafeJoin(cache2.get("phase-3")), is(Optional.of("third")));
417
418 assertThat(unsafeJoin(cache3.get("phase-3")), is(Optional.of("third")));
419 assertThat(invocationsOfBegunTxns, is(4));
420 }
421
422 @Test
423 public void verify_txns_sync_discard_sync() {
424 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
425 .defaultTtl(Duration.ofSeconds(60))
426 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
427 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
428 .entryCountHint(100)
429 .build();
430
431 final TransactionalExternalCache<String> cache1 = vCacheFactory().getTransactionalExternalCache(
432 "sync_discard_sync-1", StringMarshalling.pair(), settings);
433 assertThat(invocationsOfBegunTxns, is(0));
434
435 cache1.put("updated-key", "first1", PUT_ALWAYS);
436 assertThat(invocationsOfBegunTxns, is(1));
437 cache1.put("phase-1", "first", PUT_ALWAYS);
438
439 vCacheLifecycleManager().transactionSync(currentRequestContext());
440
441 final TransactionalExternalCache<String> cache2 = vCacheFactory().getTransactionalExternalCache(
442 "sync_discard_sync-2", StringMarshalling.pair(), settings);
443
444 assertThat(invocationsOfBegunTxns, is(1));
445 cache1.put("updated-key", "second1", PUT_ALWAYS);
446 assertThat(invocationsOfBegunTxns, is(2));
447 cache2.put("updated-key", "second2", PUT_ALWAYS);
448 cache1.put("phase-2", "second", PUT_ALWAYS);
449 cache2.put("phase-2", "second", PUT_ALWAYS);
450
451 vCacheLifecycleManager().transactionDiscard(currentRequestContext());
452
453 final TransactionalExternalCache<String> cache3 = vCacheFactory().getTransactionalExternalCache(
454 "sync_discard_sync-3", StringMarshalling.pair(), settings);
455
456 assertThat(invocationsOfBegunTxns, is(2));
457 cache1.put("updated-key", "third1", PUT_ALWAYS);
458 assertThat(invocationsOfBegunTxns, is(3));
459 cache2.put("updated-key", "third2", PUT_ALWAYS);
460 cache1.put("phase-3", "third", PUT_ALWAYS);
461 cache2.put("phase-3", "third", PUT_ALWAYS);
462 cache3.put("phase-3", "third", PUT_ALWAYS);
463
464 vCacheLifecycleManager().transactionSync(currentRequestContext());
465
466 forceNewRequestContext();
467
468 assertThat(invocationsOfBegunTxns, is(3));
469 assertThat(unsafeJoin(cache1.get("updated-key")), is(Optional.of("third1")));
470 assertThat(invocationsOfBegunTxns, is(4));
471 assertThat(unsafeJoin(cache1.get("phase-1")), is(Optional.of("first")));
472 assertThat(unsafeJoin(cache1.get("phase-2")), is(Optional.empty()));
473 assertThat(unsafeJoin(cache1.get("phase-3")), is(Optional.of("third")));
474
475 assertThat(unsafeJoin(cache2.get("updated-key")), is(Optional.of("third2")));
476 assertThat(unsafeJoin(cache2.get("phase-2")), is(Optional.empty()));
477 assertThat(unsafeJoin(cache2.get("phase-3")), is(Optional.of("third")));
478
479 assertThat(unsafeJoin(cache3.get("phase-3")), is(Optional.of("third")));
480 assertThat(invocationsOfBegunTxns, is(4));
481 }
482
483 @Test
484 public void verify_txns_discard_sync_discard() {
485 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
486 .defaultTtl(Duration.ofSeconds(60))
487 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
488 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
489 .entryCountHint(100)
490 .build();
491
492 final TransactionalExternalCache<String> cache1 = vCacheFactory().getTransactionalExternalCache(
493 "discard_sync_discard-1", StringMarshalling.pair(), settings);
494
495 cache1.put("updated-key", "first1", PUT_ALWAYS);
496 cache1.put("phase-1", "first", PUT_ALWAYS);
497
498 vCacheLifecycleManager().transactionDiscard(currentRequestContext());
499
500 final TransactionalExternalCache<String> cache2 = vCacheFactory().getTransactionalExternalCache(
501 "discard_sync_discard-2", StringMarshalling.pair(), settings);
502
503 cache1.put("updated-key", "second1", PUT_ALWAYS);
504 cache2.put("updated-key", "second2", PUT_ALWAYS);
505 cache1.put("phase-2", "second", PUT_ALWAYS);
506 cache2.put("phase-2", "second", PUT_ALWAYS);
507
508 vCacheLifecycleManager().transactionSync(currentRequestContext());
509
510 final TransactionalExternalCache<String> cache3 = vCacheFactory().getTransactionalExternalCache(
511 "discard_sync_discard-3", StringMarshalling.pair(), settings);
512
513 cache1.put("updated-key", "third1", PUT_ALWAYS);
514 cache2.put("updated-key", "third2", PUT_ALWAYS);
515 cache1.put("phase-3", "third", PUT_ALWAYS);
516 cache2.put("phase-3", "third", PUT_ALWAYS);
517 cache3.put("phase-3", "third", PUT_ALWAYS);
518
519
520 vCacheLifecycleManager().transactionDiscard(currentRequestContext());
521
522 forceNewRequestContext();
523
524 assertThat(unsafeJoin(cache1.get("updated-key")), is(Optional.of("second1")));
525 assertThat(unsafeJoin(cache1.get("phase-1")), is(Optional.empty()));
526 assertThat(unsafeJoin(cache1.get("phase-2")), is(Optional.of("second")));
527 assertThat(unsafeJoin(cache1.get("phase-3")), is(Optional.empty()));
528
529 assertThat(unsafeJoin(cache2.get("updated-key")), is(Optional.of("second2")));
530 assertThat(unsafeJoin(cache2.get("phase-2")), is(Optional.of("second")));
531 assertThat(unsafeJoin(cache2.get("phase-3")), is(Optional.empty()));
532
533 assertThat(unsafeJoin(cache3.get("phase-3")), is(Optional.empty()));
534 assertThat(invocationsOfBegunTxns, is(4));
535 }
536
537 @Test
538 public void verify_txns_discard_discard_discard() {
539 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
540 .defaultTtl(Duration.ofSeconds(60))
541 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
542 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
543 .entryCountHint(100)
544 .build();
545
546 final TransactionalExternalCache<String> cache1 = vCacheFactory().getTransactionalExternalCache(
547 "discard_discard_discard-1", StringMarshalling.pair(), settings);
548
549 cache1.put("updated-key", "first1", PUT_ALWAYS);
550 cache1.put("phase-1", "first", PUT_ALWAYS);
551
552 vCacheLifecycleManager().transactionDiscard(currentRequestContext());
553
554 final TransactionalExternalCache<String> cache2 = vCacheFactory().getTransactionalExternalCache(
555 "discard_discard_discard-2", StringMarshalling.pair(), settings);
556
557 cache1.put("updated-key", "second1", PUT_ALWAYS);
558 cache2.put("updated-key", "second2", PUT_ALWAYS);
559 cache1.put("phase-2", "second", PUT_ALWAYS);
560 cache2.put("phase-2", "second", PUT_ALWAYS);
561
562 vCacheLifecycleManager().transactionDiscard(currentRequestContext());
563
564 final TransactionalExternalCache<String> cache3 = vCacheFactory().getTransactionalExternalCache(
565 "discard_discard_discard-3", StringMarshalling.pair(), settings);
566
567 cache1.put("updated-key", "third1", PUT_ALWAYS);
568 cache2.put("updated-key", "third2", PUT_ALWAYS);
569 cache1.put("phase-3", "third", PUT_ALWAYS);
570 cache2.put("phase-3", "third", PUT_ALWAYS);
571 cache3.put("phase-3", "third", PUT_ALWAYS);
572
573 vCacheLifecycleManager().transactionDiscard(currentRequestContext());
574
575 forceNewRequestContext();
576
577 assertThat(unsafeJoin(cache1.get("updated-key")), is(Optional.empty()));
578 assertThat(unsafeJoin(cache1.get("phase-1")), is(Optional.empty()));
579 assertThat(unsafeJoin(cache1.get("phase-2")), is(Optional.empty()));
580 assertThat(unsafeJoin(cache1.get("phase-3")), is(Optional.empty()));
581
582 assertThat(unsafeJoin(cache2.get("updated-key")), is(Optional.empty()));
583 assertThat(unsafeJoin(cache2.get("phase-2")), is(Optional.empty()));
584 assertThat(unsafeJoin(cache2.get("phase-3")), is(Optional.empty()));
585
586 assertThat(unsafeJoin(cache3.get("phase-3")), is(Optional.empty()));
587 assertThat(invocationsOfBegunTxns, is(4));
588 }
589
590 @Test
591 public void duplicate_names_different_policys() {
592 final DirectExternalCache<String> directCache =
593 vCacheFactory().getDirectExternalCache(
594 "duplicate", StringMarshalling.pair(), new ExternalCacheSettingsBuilder().build());
595
596 thrown.expect(ExternalCacheException.class);
597 thrown.expectMessage("Failed due to CREATION_FAILURE");
598
599 final StableReadExternalCache<String> stableCache =
600 vCacheFactory().getStableReadExternalCache(
601 "duplicate", StringMarshalling.pair(), new ExternalCacheSettingsBuilder().build());
602 }
603
604 @Test
605 public void directexternalcache_duplicate_obtain() {
606 final DirectExternalCache<String> firstTime =
607 vCacheFactory().getDirectExternalCache(
608 "duplicate", dodgyPair("first"), new ExternalCacheSettingsBuilder().build());
609
610 final CompletionStage<Boolean> put1 = firstTime.put("key", "ignored", PUT_ALWAYS);
611 assertThat(VCacheUtils.unsafeJoin(put1), is(true));
612
613 final CompletionStage<Optional<String>> get1 = firstTime.get("key");
614 assertThat(VCacheUtils.unsafeJoin(get1), is(Optional.of("first")));
615
616 final DirectExternalCache<String> secondTime =
617 vCacheFactory().getDirectExternalCache(
618 "duplicate", dodgyPair("second"), new ExternalCacheSettingsBuilder().build());
619
620 final CompletionStage<Optional<String>> get2 = secondTime.get("key");
621 assertThat(VCacheUtils.unsafeJoin(get2), is(Optional.of("second")));
622 }
623
624 @Test
625 public void stablereadexternalcache_duplicate_obtain() {
626 final StableReadExternalCache<String> firstTime =
627 vCacheFactory().getStableReadExternalCache(
628 "duplicate", dodgyPair("first"), new ExternalCacheSettingsBuilder().build());
629
630 final CompletionStage<Boolean> put1 = firstTime.put("key", "ignored", PUT_ALWAYS);
631 assertThat(VCacheUtils.unsafeJoin(put1), is(true));
632
633 forceNewRequestContext();
634 final CompletionStage<Optional<String>> get1 = firstTime.get("key");
635 assertThat(VCacheUtils.unsafeJoin(get1), is(Optional.of("first")));
636
637 final StableReadExternalCache<String> secondTime =
638 vCacheFactory().getStableReadExternalCache(
639 "duplicate", dodgyPair("second"), new ExternalCacheSettingsBuilder().build());
640 forceNewRequestContext();
641
642 final CompletionStage<Optional<String>> get2 = secondTime.get("key");
643 assertThat(VCacheUtils.unsafeJoin(get2), is(Optional.of("second")));
644 }
645
646 @Test
647 public void txnexternalcache_duplicate_obtain() {
648 final TransactionalExternalCache<String> firstTime =
649 vCacheFactory().getTransactionalExternalCache(
650 "duplicate", dodgyPair("first"), new ExternalCacheSettingsBuilder().build());
651
652 firstTime.put("key", "ignored", PUT_ALWAYS);
653 vCacheLifecycleManager().transactionSync(currentRequestContext());
654
655 forceNewRequestContext();
656 final CompletionStage<Optional<String>> get1 = firstTime.get("key");
657 assertThat(VCacheUtils.unsafeJoin(get1), is(Optional.of("first")));
658
659 final TransactionalExternalCache<String> secondTime =
660 vCacheFactory().getTransactionalExternalCache(
661 "duplicate", dodgyPair("second"), new ExternalCacheSettingsBuilder().build());
662
663 forceNewRequestContext();
664 final CompletionStage<Optional<String>> get2 = secondTime.get("key");
665 assertThat(VCacheUtils.unsafeJoin(get2), is(Optional.of("second")));
666 }
667
668 private static MarshallingPair<String> dodgyPair(String returning) {
669 return new MarshallingPair<>(String::getBytes, b -> returning);
670 }
671
672 @Test
673 public void detect_illegal_recursive_get_supplier() {
674 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
675 .defaultTtl(Duration.ofSeconds(60))
676 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
677 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
678 .entryCountHint(100)
679 .build();
680
681 final StableReadExternalCache<String> cache = vCacheFactory().getStableReadExternalCache(
682 "my-stable-read-cache", StringMarshalling.pair(), settings);
683
684 final CompletionStage<String> get1 = cache.get("recursive", () ->
685 unsafeJoin(cache.get("recursive", () -> "ignored")));
686 assertThat(get1, not(successful()));
687 }
688
689 @Ignore
690 @Test
691 public void handle_legal_recursive_get_supplier() {
692 final ExternalCacheSettings settings = new ExternalCacheSettingsBuilder()
693 .defaultTtl(Duration.ofSeconds(60))
694 .entryGrowthRateHint(ChangeRate.LOW_CHANGE)
695 .dataChangeRateHint(ChangeRate.LOW_CHANGE)
696 .entryCountHint(100)
697 .build();
698
699 final StableReadExternalCache<String> cache = vCacheFactory().getStableReadExternalCache(
700 "my-stable-read-cache", StringMarshalling.pair(), settings);
701
702 final CompletionStage<String> get1 = cache.get("recursive", () ->
703 unsafeJoin(cache.get("recursive2", () -> "pass")));
704 assertThat(get1, successfulWith(is("pass")));
705 }
706 }