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