public EvictionPolicy build() { return new EvictionPolicy(maxSizeBytes, maxEntries, expireAfterAccess, expireAfterAccessTimeUnit, expireAfterWrite, expireAfterWriteTimeUnit); }
@Override public LruNormalizedCache create(final RecordFieldJsonAdapter fieldAdapter) { return new LruNormalizedCache(evictionPolicy); } }
public static EvictionPolicy.Builder builder() { return new EvictionPolicy.Builder(); }
@Test public void testEvictionPolicyBuilder() { final EvictionPolicy policy = EvictionPolicy.builder() .maxSizeBytes(100) .maxEntries(50) .expireAfterAccess(5, TimeUnit.HOURS) .expireAfterWrite(10, TimeUnit.DAYS) .build(); assertThat(policy.maxSizeBytes().get()).isEqualTo(100); assertThat(policy.maxEntries().get()).isEqualTo(50); assertThat(policy.expireAfterAccess().get()).isEqualTo(5); assertThat(policy.expireAfterAccessTimeUnit().get()).isEqualTo(TimeUnit.HOURS); assertThat(policy.expireAfterWrite().get()).isEqualTo(10); assertThat(policy.expireAfterWriteTimeUnit().get()).isEqualTo(TimeUnit.DAYS); }
LruNormalizedCache(EvictionPolicy evictionPolicy) { final CacheBuilder<Object, Object> lruCacheBuilder = CacheBuilder.newBuilder(); if (evictionPolicy.maxSizeBytes().isPresent()) { lruCacheBuilder.maximumWeight(evictionPolicy.maxSizeBytes().get()) .weigher(new Weigher<String, Record>() { @Override public int weigh(String key, Record value) { return key.getBytes(Charset.defaultCharset()).length + value.sizeEstimateBytes(); } }); } if (evictionPolicy.maxEntries().isPresent()) { lruCacheBuilder.maximumSize(evictionPolicy.maxEntries().get()); } if (evictionPolicy.expireAfterAccess().isPresent()) { lruCacheBuilder.expireAfterAccess(evictionPolicy.expireAfterAccess().get(), evictionPolicy.expireAfterAccessTimeUnit().get()); } if (evictionPolicy.expireAfterWrite().isPresent()) { lruCacheBuilder.expireAfterWrite(evictionPolicy.expireAfterWrite().get(), evictionPolicy.expireAfterWriteTimeUnit().get()); } lruCache = lruCacheBuilder.build(); }
@Test public void testLoad_recordNotPresent() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024).build ()).create(basicFieldAdapter); final Record record = lruCache.loadRecord("key1", CacheHeaders.NONE); assertThat(record).isNull(); }
@Test public void testClearPrimaryCache() { LruNormalizedCacheFactory secondaryCacheFactory = new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION); LruNormalizedCache primaryCache = (LruNormalizedCache) new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION) .chain(secondaryCacheFactory).createChain(basicFieldAdapter); Record record = Record.builder("key").build(); primaryCache.merge(record, CacheHeaders.NONE); primaryCache.clearCurrentCache(); assertThat(primaryCache.nextCache().get() .loadRecord("key", CacheHeaders.NONE)).isNotNull(); assertThat(primaryCache.nextCache().get() .loadRecord("key", CacheHeaders.NONE)).isNotNull(); }
@Test public void testSaveAndLoad_singleRecord() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024).build ()).create(basicFieldAdapter); Record testRecord = createTestRecord("1"); lruCache.merge(testRecord, CacheHeaders.NONE); assertTestRecordPresentAndAccurate(testRecord, lruCache); }
@SuppressWarnings("ResultOfMethodCallIgnored") @Override public void clearAll() { nextCache().apply(new Action<NormalizedCache>() { @Override public void apply(@NotNull NormalizedCache cache) { cache.clearAll(); } }); clearCurrentCache(); }
@Test public void testSaveAndLoad_multipleRecord_readMultiple() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024).build ()).create(basicFieldAdapter); Record testRecord1 = createTestRecord("1"); Record testRecord2 = createTestRecord("2"); Record testRecord3 = createTestRecord("3"); List<Record> inputRecords = Arrays.asList(testRecord1, testRecord2, testRecord3); lruCache.merge(inputRecords, CacheHeaders.NONE); final Collection<Record> readRecords = lruCache.loadRecords(Arrays.asList("key1", "key2", "key3"), CacheHeaders.NONE); //noinspection ResultOfMethodCallIgnored assertThat(readRecords).containsExactlyElementsIn(inputRecords); }
@Override public Record call() throws Exception { return nextCache().flatMap(new Function<NormalizedCache, Optional<Record>>() { @NotNull @Override public Optional<Record> apply(@NotNull NormalizedCache cache) { return Optional.fromNullable(cache.loadRecord(key, cacheHeaders)); } }).get(); // lruCache.get(key, callable) requires non-null. } });
@Test public void testDualCache_recordNotPresent() { LruNormalizedCacheFactory secondaryCacheFactory = new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION); NormalizedCache primaryCacheStore = new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION) .chain(secondaryCacheFactory).createChain(basicFieldAdapter); assertThat(primaryCacheStore.loadRecord("not_present_id", CacheHeaders.NONE)).isNull(); }
@Test public void testHeader_evictAfterRead() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024).build ()).create(basicFieldAdapter); Record testRecord = createTestRecord("1"); lruCache.merge(testRecord, CacheHeaders.NONE); final Record record = lruCache.loadRecord("key1", CacheHeaders.builder().addHeader(ApolloCacheHeaders.EVICT_AFTER_READ, "true") .build()); assertThat(record).isNotNull(); final Record nullRecord = lruCache.loadRecord("key1", CacheHeaders.builder().addHeader(ApolloCacheHeaders.EVICT_AFTER_READ, "true") .build()); assertThat(nullRecord).isNull(); }
@Test public void testSaveAndLoad_multipleRecord_readSingle() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024).build ()).create(basicFieldAdapter); Record testRecord1 = createTestRecord("1"); Record testRecord2 = createTestRecord("2"); Record testRecord3 = createTestRecord("3"); List<Record> records = Arrays.asList(testRecord1, testRecord2, testRecord3); lruCache.merge(records, CacheHeaders.NONE); assertTestRecordPresentAndAccurate(testRecord1, lruCache); assertTestRecordPresentAndAccurate(testRecord2, lruCache); assertTestRecordPresentAndAccurate(testRecord3, lruCache); }
@Override public Map<Class, Map<String, Record>> dump() { Map<Class, Map<String, Record>> dump = new LinkedHashMap<>(); dump.put(this.getClass(), Collections.unmodifiableMap(new LinkedHashMap<>(lruCache.asMap()))); if (nextCache().isPresent()) { dump.putAll(nextCache().get().dump()); } return dump; } }
@Test public void testClearAll() { LruNormalizedCacheFactory secondaryCacheFactory = new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION); NormalizedCache primaryCacheStore = new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION) .chain(secondaryCacheFactory).createChain(basicFieldAdapter); Record record = Record.builder("key").build(); primaryCacheStore.merge(record, CacheHeaders.NONE); primaryCacheStore.clearAll(); assertThat(primaryCacheStore.loadRecord("key", CacheHeaders.NONE)).isNull(); }
@Test public void testHeader_noCache() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024).build ()).create(basicFieldAdapter); Record testRecord = createTestRecord("1"); lruCache.merge(testRecord, CacheHeaders.builder().addHeader(ApolloCacheHeaders.DO_NOT_STORE, "true").build()); final Record record = lruCache.loadRecord("key1", CacheHeaders.NONE); assertThat(record).isNull(); Record testRecord1 = createTestRecord("1"); Record testRecord2 = createTestRecord("2"); Collection<Record> testRecordSet = new HashSet<>(); testRecordSet.add(testRecord1); testRecordSet.add(testRecord2); lruCache.merge(testRecordSet, CacheHeaders.builder().addHeader(ApolloCacheHeaders.DO_NOT_STORE, "true").build()); final Record record1 = lruCache.loadRecord("key1", CacheHeaders.NONE); final Record record2 = lruCache.loadRecord("key2", CacheHeaders.NONE); assertThat(record1).isNull(); assertThat(record2).isNull(); }
@Test public void testClearSecondaryCache() { LruNormalizedCacheFactory secondaryCacheFactory = new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION); NormalizedCache primaryCache = new LruNormalizedCacheFactory(EvictionPolicy.NO_EVICTION) .chain(secondaryCacheFactory).createChain(basicFieldAdapter); Record record = Record.builder("key").build(); primaryCache.merge(record, CacheHeaders.NONE); primaryCache.nextCache().get().clearAll(); assertThat(primaryCache.nextCache().get().loadRecord("key", CacheHeaders.NONE)).isNull(); }
@Test public void testEviction() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(2000) .build()).create(basicFieldAdapter); Record.Builder testRecord1Builder = Record.builder("key1"); testRecord1Builder.addField("a", new String(new byte[1100], Charset.defaultCharset())); Record testRecord1 = testRecord1Builder.build(); Record.Builder testRecord2Builder = Record.builder("key2"); testRecord2Builder.addField("a", new String(new byte[1100], Charset.defaultCharset())); Record testRecord2 = testRecord2Builder.build(); Record.Builder testRecord3Builder = Record.builder("key3"); testRecord3Builder.addField("a", new String(new byte[10], Charset.defaultCharset())); Record testRecord3 = testRecord3Builder.build(); List<Record> records = Arrays.asList( testRecord1, testRecord2, testRecord3 ); lruCache.merge(records, CacheHeaders.NONE); //Cache does not reveal exactly how it handles eviction, but appears //to evict more than is strictly necessary. Regardless, any sane eviction //strategy should leave the third record in this test case, and evict the first record. assertThat(lruCache.loadRecord("key1", CacheHeaders.NONE)).isNull(); assertThat(lruCache.loadRecord("key3", CacheHeaders.NONE)).isNotNull(); }
@Test public void testEviction_recordChange() { LruNormalizedCache lruCache = new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(2000) .build()).create(basicFieldAdapter); testRecord3 ); lruCache.merge(records, CacheHeaders.NONE); assertThat(lruCache.loadRecord("key1", CacheHeaders.NONE)).isNotNull(); assertThat(lruCache.loadRecord("key2", CacheHeaders.NONE)).isNotNull(); assertThat(lruCache.loadRecord("key3", CacheHeaders.NONE)).isNotNull(); Record largeTestRecord = largeTestRecordBuilder.build(); lruCache.merge(largeTestRecord, CacheHeaders.NONE); assertThat(lruCache.loadRecord("key1", CacheHeaders.NONE)).isNull(); assertThat(lruCache.loadRecord("key2", CacheHeaders.NONE)).isNotNull(); assertThat(lruCache.loadRecord("key3", CacheHeaders.NONE)).isNotNull();