@Override public void delete(K key) throws Exception { delegate.delete(key); }
public void performOperation(CacheLoaderWriter<K, V> cacheLoaderWriter) throws Exception { cacheLoaderWriter.delete(key); }
/** * Deletes multiple mappings. * <p> * By using a {@link BulkCacheWritingException} implementors can report partial success. Any other exception will * be thrown back to the {@code Cache} user through a {@link BulkCacheWritingException} indicating all deletes failed. * * @param keys the keys to delete * * @throws BulkCacheWritingException in case of partial success * @throws Exception in case no values can be loaded */ default void deleteAll(Iterable<? extends K> keys) throws BulkCacheWritingException, Exception { for (K k : keys) { delete(k); } }
/** * Delete the key from the loader-writer. * * @param key the key being removed * @param e the triggered failure */ @Override public void removeFailure(K key, StoreAccessException e) { try { loaderWriter.delete(key); } catch(Exception e1) { throw ExceptionFactory.newCacheWritingException(e1, e); } finally { cleanup(key, e); } }
@Override public ValueHolder<V> computeAndGet(K key, BiFunction<? super K, ? super V, ? extends V> mappingFunction, Supplier<Boolean> replaceEqual, Supplier<Boolean> invokeWriter) throws StoreAccessException { BiFunction<? super K, ? super V, ? extends V> remappingFunction = (mappedKey, mappedValue) -> { V newValue = mappingFunction.apply(mappedKey, mappedValue); if (invokeWriter.get()) { try { if (newValue != null) { cacheLoaderWriter.write(mappedKey, newValue); } else { cacheLoaderWriter.delete(mappedKey); } } catch (Exception e) { throw new StorePassThroughException(newCacheWritingException(e)); } } return newValue; }; return delegate.computeAndGet(key, remappingFunction, replaceEqual, SUPPLY_FALSE); }
@Override public boolean remove(K key) throws StoreAccessException { boolean[] modified = { false }; BiFunction<K, V, V> remappingFunction = (key1, previousValue) -> { modified[0] = (previousValue != null); try { cacheLoaderWriter.delete(key1); } catch (Exception e) { throw new StorePassThroughException(newCacheWritingException(e)); } return null; }; delegate.getAndCompute(key, remappingFunction); return modified[0]; }
@Test public void testRemove2ArgsWithNoCacheEntry_should_not_call_writer() throws Exception { doThrow(new Exception("Mock Exception: cannot write 1")).when(cacheLoaderWriter).delete(eq(1)); testCache.remove(1, "one"); }
@Test public void removeFailure_failedLoaderWriter() throws Exception { doThrow(exception).when(loaderWriter).delete(1); assertThatThrownBy(() -> strategy.removeFailure(1, accessException)) .isExactlyInstanceOf(CacheWritingException.class) .hasCause(exception); verify(store).obliterate(1); verify(loaderWriter).delete(1); }
@Test public void testRemove2ArgsWithNotMatchingCacheEntry_should_not_call_writer() throws Exception { doThrow(new Exception("Mock Exception: cannot write 1")).when(cacheLoaderWriter).delete(eq(1)); testCache.put(1, "un"); testCache.remove(1, "one"); }
@Test public void testRemoveWithWriterException() throws Exception { doThrow(new Exception("Mock Exception: cannot write 1")).when(cacheLoaderWriter).delete(eq(1)); try { testCache.remove(1); fail("expected CacheWritingException"); } catch (CacheWritingException ex) { // expected } }
@Test public void removeFailure1_deleteFails() throws Exception { when(loaderWriter.load(1)).thenReturn(1L); doThrow(exception).when(loaderWriter).delete(1); assertThatThrownBy(() -> strategy.removeFailure(1, 1L, accessException)) .isExactlyInstanceOf(CacheWritingException.class) .hasCause(exception); verify(store).obliterate(1); verify(loaderWriter).load(1); verify(loaderWriter).delete(1); }
@Test @SuppressWarnings("unchecked") public void testSimpleRemove2ArgsWithLoaderAndWriter_existsInStore() throws Exception { testCache.put(1, "un"); reset(cacheLoaderWriter); assertThat(testCache.remove(1, "un"), is(true)); verify(cacheLoaderWriter, times(1)).delete(eq(1)); verifyNoMoreInteractions(cacheLoaderWriter); }
@Test public void removeFailure1_foundEquals() throws Exception { when(loaderWriter.load(1)).thenReturn(1L); assertThat(strategy.removeFailure(1, 1L, accessException)).isTrue(); verify(store).obliterate(1); verify(loaderWriter).load(1); verify(loaderWriter).delete(1); }
@Test public void removeFailure() throws Exception { strategy.removeFailure(1, accessException); verify(store).obliterate(1); verify(loaderWriter).delete(1); }
@Test public void testSimpleRemove2ArgsWithLoaderAndWriter_existsInSor() throws Exception { when(cacheLoaderWriter.load(eq(1))).thenAnswer((Answer) invocation -> "un"); assertThat(testCache.containsKey(1), is(false)); assertThat(testCache.remove(1, "un"), is(true)); verify(cacheLoaderWriter, times(1)).load(eq(1)); verify(cacheLoaderWriter, times(1)).delete(eq(1)); }
@Test public void testRemove2ArgsWithWriterException_should_call_writer() throws Exception { doThrow(new Exception("Mock Exception: cannot write 1")).when(cacheLoaderWriter).delete(eq(1)); testCache.put(1, "one"); try { testCache.remove(1, "one"); fail("expected CacheWritingException"); } catch (CacheWritingException ex) { // expected } }
@Test public void testRemoveValueAbsentInCacheAbsentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); @SuppressWarnings("unchecked") CacheLoaderWriter<Long, String> loaderWriter = mock(CacheLoaderWriter.class); when(storeProxy.lock(anyLong())).thenReturn(EMPTY_CHAIN); ClusteredLoaderWriterStore<Long, String> store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.remove(1L), is(false)); verify(loaderWriter, times(1)).delete(anyLong()); }
@Override public ValueHolder<V> getAndCompute(K key, BiFunction<? super K, ? super V, ? extends V> mappingFunction) throws StoreAccessException { return delegate.getAndCompute(key, (mappedKey, mappedValue) -> { V newValue = mappingFunction.apply(mappedKey, mappedValue); if (newValue == null) { try { cacheLoaderWriter.delete(mappedKey); } catch (Exception e) { throw new StorePassThroughException(newCacheWritingException(e)); } return null; } else { try { cacheLoaderWriter.write(mappedKey, newValue); } catch (Exception e) { throw new StorePassThroughException(newCacheWritingException(e)); } if (newValueAlreadyExpired(LOG, expiry, mappedKey, mappedValue, newValue)) { return null; } return newValue; } }); }
@Test public void testRemove2ArgsValuePresentInCachePresentInSOR() throws Exception { LockingServerStoreProxy storeProxy = mock(LockingServerStoreProxy.class); @SuppressWarnings("unchecked") CacheLoaderWriter<Long, String> loaderWriter = mock(CacheLoaderWriter.class); PutOperation<Long, String> operation = new PutOperation<>(1L, "one", System.currentTimeMillis()); Chain toReturn = Util.getChain(false, codec.encode(operation)); when(storeProxy.lock(anyLong())).thenReturn(toReturn); ClusteredLoaderWriterStore<Long, String> store = new ClusteredLoaderWriterStore<>(configuration, codec, resolver, storeProxy, timeSource, loaderWriter); assertThat(store.remove(1L, "one"), is(Store.RemoveStatus.REMOVED)); verify(storeProxy, times(1)).append(anyLong(), ArgumentMatchers.any(ByteBuffer.class)); verify(loaderWriter, times(0)).load(anyLong()); verify(loaderWriter, times(1)).delete(anyLong()); }
@Test public void testUnBatchedDeletedKeyReturnsNull() throws Exception { Semaphore semaphore = new Semaphore(0); @SuppressWarnings("unchecked") CacheLoaderWriter<String, String> loaderWriter = mock(CacheLoaderWriter.class); when(loaderWriter.load("key")).thenReturn("value"); doAnswer(invocation -> { semaphore.acquire(); return null; }).when(loaderWriter).delete("key"); CacheLoaderWriterProvider cacheLoaderWriterProvider = getMockedCacheLoaderWriterProvider(loaderWriter); CacheManager cacheManager = managerBuilder().using(cacheLoaderWriterProvider).build(true); try { Cache<String, String> testCache = cacheManager.createCache("testUnBatchedDeletedKeyReturnsNull", configurationBuilder() .withLoaderWriter(loaderWriter) .add(newUnBatchedWriteBehindConfiguration().build()) .build()); assertThat(testCache.get("key"), is("value")); testCache.remove("key"); assertThat(testCache.get("key"), nullValue()); } finally { semaphore.release(); cacheManager.close(); } }