@Override public long expireAfterRead(K key, CompletableFuture<V> future, long currentTime, long currentDuration) { if (isReady(future)) { long duration = delegate.expireAfterRead(key, future.join(), currentTime, currentDuration); return Math.min(duration, MAXIMUM_EXPIRY); } return ASYNC_EXPIRY; }
/** * Returns the access time for the entry after a read. * * @param node the entry in the page replacement policy * @param key the key of the entry that was read * @param value the value of the entry that was read * @param expiry the calculator for the expiration time * @param now the current time, in nanoseconds * @return the expiration time */ long expireAfterRead(Node<K, V> node, @Nullable K key, @Nullable V value, Expiry<K, V> expiry, long now) { if (expiresVariable() && (key != null) && (value != null)) { long currentDuration = Math.max(1, node.getVariableTime() - now); long duration = expiry.expireAfterRead(key, value, now, currentDuration); return isAsync ? (now + duration) : (now + Math.min(duration, MAXIMUM_EXPIRY)); } return 0L; }
@Test public void asyncExpiry_completed() { AsyncExpiry<Integer, Integer> expiry = makeAsyncExpiry( ONE_MINUTE, 2 * ONE_MINUTE, 3 * ONE_MINUTE); CompletableFuture<Integer> future = CompletableFuture.completedFuture(100); assertThat(expiry.expireAfterCreate(0, future, 1L), is(ONE_MINUTE)); verify(expiry.delegate).expireAfterCreate(0, 100, 1L); assertThat(expiry.expireAfterUpdate(0, future, 1L, 2L), is(2 * ONE_MINUTE)); verify(expiry.delegate).expireAfterUpdate(0, 100, 1L, 2L); assertThat(expiry.expireAfterRead(0, future, 1L, 2L), is(3 * ONE_MINUTE)); verify(expiry.delegate).expireAfterRead(0, 100, 1L, 2L); }
private static <K, V> AsyncExpiry<K, V> makeAsyncExpiry(long create, long update, long read) { @SuppressWarnings("unchecked") Expiry<K, V> mock = Mockito.mock(Expiry.class); when(mock.expireAfterCreate(any(), any(), anyLong())).thenReturn(create); when(mock.expireAfterUpdate(any(), any(), anyLong(), anyLong())).thenReturn(update); when(mock.expireAfterRead(any(), any(), anyLong(), anyLong())).thenReturn(read); return new AsyncExpiry<>(mock); }
@Test public void asyncExpiry_pending() { AsyncExpiry<Integer, Integer> expiry = makeAsyncExpiry(ONE_MINUTE, ONE_MINUTE, ONE_MINUTE); CompletableFuture<Integer> future = new CompletableFuture<Integer>(); assertThat(expiry.expireAfterCreate(0, future, 1L), is(ASYNC_EXPIRY)); verify(expiry.delegate, never()).expireAfterCreate(any(), any(), anyLong()); assertThat(expiry.expireAfterUpdate(0, future, 1L, 2L), is(ASYNC_EXPIRY)); verify(expiry.delegate, never()).expireAfterUpdate(any(), any(), anyLong(), anyLong()); assertThat(expiry.expireAfterRead(0, future, 1L, 2L), is(ASYNC_EXPIRY)); verify(expiry.delegate, never()).expireAfterRead(any(), any(), anyLong(), anyLong()); }
@Override public <K, V> Expiry<K, V> createExpiry(Expire expiryTime) { @SuppressWarnings("unchecked") Expiry<K, V> mock = Mockito.mock(Expiry.class); when(mock.expireAfterCreate(any(), any(), anyLong())) .thenReturn(expiryTime.timeNanos()); when(mock.expireAfterUpdate(any(), any(), anyLong(), anyLong())) .thenReturn(expiryTime.timeNanos()); when(mock.expireAfterRead(any(), any(), anyLong(), anyLong())) .thenReturn(expiryTime.timeNanos()); return mock; } },
@BeforeMethod public void setup() { Mockito.reset(expiry); when(expiry.expireAfterCreate(anyInt(), anyInt(), anyLong())).thenReturn(ONE_MINUTE); when(expiry.expireAfterUpdate(anyInt(), anyInt(), anyLong(), anyLong())).thenReturn(ONE_MINUTE); when(expiry.expireAfterRead(anyInt(), anyInt(), anyLong(), anyLong())).thenReturn(ONE_MINUTE); }
@BeforeMethod public void setup() { Mockito.reset(expiry); when(expiry.expireAfterCreate(anyInt(), anyInt(), anyLong())).thenReturn(ONE_MINUTE); when(expiry.expireAfterUpdate(anyInt(), anyInt(), anyLong(), anyLong())).thenReturn(ONE_MINUTE); when(expiry.expireAfterRead(anyInt(), anyInt(), anyLong(), anyLong())).thenReturn(ONE_MINUTE); }
@CacheSpec(implementation = Implementation.Caffeine, population = Population.FULL, expiry = CacheExpiry.MOCKITO) @Test(dataProvider = "caches", expectedExceptions = ExpirationException.class) public void getIfPresent_expiryFails(Cache<Integer, Integer> cache, CacheContext context) { try { context.ticker().advance(1, TimeUnit.HOURS); when(context.expiry().expireAfterRead(any(), any(), anyLong(), anyLong())) .thenThrow(ExpirationException.class); cache.getIfPresent(context.firstKey()); } finally { context.ticker().advance(-1, TimeUnit.HOURS); assertThat(cache.asMap(), equalTo(context.original())); } }
@CacheSpec(implementation = Implementation.Caffeine, population = Population.FULL, expiry = CacheExpiry.MOCKITO) @Test(dataProvider = "caches", expectedExceptions = ExpirationException.class) public void get_expiryFails_read(Cache<Integer, Integer> cache, CacheContext context) { try { context.ticker().advance(1, TimeUnit.HOURS); when(context.expiry().expireAfterRead(any(), any(), anyLong(), anyLong())) .thenThrow(ExpirationException.class); cache.get(context.firstKey(), identity()); } finally { context.ticker().advance(-1, TimeUnit.HOURS); assertThat(cache.asMap(), equalTo(context.original())); } }
@CacheSpec(implementation = Implementation.Caffeine, population = Population.FULL, expiry = CacheExpiry.MOCKITO) @Test(dataProvider = "caches", expectedExceptions = ExpirationException.class) public void getAllPresent_expiryFails(Cache<Integer, Integer> cache, CacheContext context) { try { context.ticker().advance(1, TimeUnit.HOURS); when(context.expiry().expireAfterRead(any(), any(), anyLong(), anyLong())) .thenThrow(ExpirationException.class); cache.getAllPresent(context.firstMiddleLastKeys()); } finally { context.ticker().advance(-1, TimeUnit.HOURS); assertThat(cache.asMap(), equalTo(context.original())); } }
@Test public void configured() { jcache.put(KEY_1, VALUE_1); verify(expiry, times(1)).expireAfterCreate(anyInt(), anyInt(), anyLong()); jcache.put(KEY_1, VALUE_2); verify(expiry).expireAfterUpdate(anyInt(), anyInt(), anyLong(), anyLong()); jcache.get(KEY_1); verify(expiry).expireAfterRead(anyInt(), anyInt(), anyLong(), anyLong()); } }
@Test public void expiry() { jcache.put(KEY_1, VALUE_1); verify(expiry, times(1)).expireAfterCreate(anyInt(), anyInt(), anyLong()); jcache.put(KEY_1, VALUE_2); verify(expiry).expireAfterUpdate(anyInt(), anyInt(), anyLong(), anyLong()); jcache.get(KEY_1); verify(expiry).expireAfterRead(anyInt(), anyInt(), anyLong(), anyLong()); }
@Override public long expireAfterRead(K key, CompletableFuture<V> future, long currentTime, long currentDuration) { if (isReady(future)) { long duration = delegate.expireAfterRead(key, future.join(), currentTime, currentDuration); return Math.min(duration, MAXIMUM_EXPIRY); } return ASYNC_EXPIRY; }
/** * Returns the access time for the entry after a read. * * @param node the entry in the page replacement policy * @param key the key of the entry that was read * @param value the value of the entry that was read * @param expiry the calculator for the expiration time * @param now the current time, in nanoseconds * @return the expiration time */ long expireAfterRead(Node<K, V> node, @Nullable K key, @Nullable V value, Expiry<K, V> expiry, long now) { if (expiresVariable() && (key != null) && (value != null)) { long currentDuration = Math.max(1, node.getVariableTime() - now); long duration = expiry.expireAfterRead(key, value, now, currentDuration); return isAsync ? (now + duration) : (now + Math.min(duration, MAXIMUM_EXPIRY)); } return 0L; }