@Override public CompletableFuture<Void> deleteAsync(K key) { Preconditions.checkNotNull(writeFn, "null writeFn"); return writeFn.deleteAsync(key); }
/** * Delete the {@code record} with specified {@code key} from the remote store. * The default implementation calls deleteAsync and blocks on the completion afterwards. * @param key key to the table record to be deleted */ default void delete(K key) { try { deleteAsync(key).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("DELETE failed for " + key, e); } }
/** * Delete the {@code record} with specified {@code key} from the remote store. * The default implementation calls deleteAsync and blocks on the completion afterwards. * @param key key to the table record to be deleted */ default void delete(K key) { try { deleteAsync(key).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("DELETE failed for " + key, e); } }
/** * Delete the {@code record} with specified {@code key} from the remote store. * The default implementation calls deleteAsync and blocks on the completion afterwards. * @param key key to the table record to be deleted */ default void delete(K key) { try { deleteAsync(key).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("DELETE failed for " + key, e); } }
/** * Delete the {@code record} with specified {@code key} from the remote store. * The default implementation calls deleteAsync and blocks on the completion afterwards. * @param key key to the table record to be deleted */ default void delete(K key) { try { deleteAsync(key).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("DELETE failed for " + key, e); } }
/** * Delete the {@code record} with specified {@code key} from the remote store. * The default implementation calls deleteAsync and blocks on the completion afterwards. * @param key key to the table record to be deleted */ default void delete(K key) { try { deleteAsync(key).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("DELETE failed for " + key, e); } }
@Override public CompletableFuture<Void> deleteAsync(K key) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.deleteAsync(key)) .exceptionally(e -> { throw new SamzaException("Failed to delete the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> deleteAsync(K key) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.deleteAsync(key)) .exceptionally(e -> { throw new SamzaException("Failed to delete the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> deleteAsync(K key) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.deleteAsync(key)) .exceptionally(e -> { throw new SamzaException("Failed to delete the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> deleteAsync(K key) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.deleteAsync(key)) .exceptionally(e -> { throw new SamzaException("Failed to delete the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> deleteAsync(K key) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.deleteAsync(key)) .exceptionally(e -> { throw new SamzaException("Failed to delete the record for " + key + " after retries.", e); }); }
private void doTestDelete(boolean sync, boolean error) throws Exception { TableWriteFunction<String, String> writeFn = mock(TableWriteFunction.class); RemoteTable<String, String> table = getTable("testDelete-" + sync + error, mock(TableReadFunction.class), writeFn, false); CompletableFuture<Void> future; if (error) { future = new CompletableFuture(); future.completeExceptionally(new RuntimeException("Test exception")); } else { future = CompletableFuture.completedFuture(null); } // Sync is backed by async so needs to mock the async method doReturn(future).when(writeFn).deleteAsync(any()); ArgumentCaptor<String> argCaptor = ArgumentCaptor.forClass(String.class); if (sync) { table.delete("foo"); } else { table.deleteAsync("foo").get(); } verify(writeFn, times(1)).deleteAsync(argCaptor.capture()); Assert.assertEquals("foo", argCaptor.getValue()); verify(table.writeRateLimiter, times(1)).throttle(anyString()); }
@Test public void testDeleteAsync() { verifyFailure(() -> roTable.deleteAsync(1)); rwTable.deleteAsync(1); verify(writeFn, times(1)).deleteAsync(any()); } @Test
if (!error) { if (isDelete) { doReturn(successFuture).when(writeFn).deleteAsync(any()); } else { doReturn(successFuture).when(writeFn).putAsync(any(), any()); doReturn(failureFuture).when(writeFn).deleteAsync(any()); } else { doReturn(failureFuture).when(writeFn).putAsync(any(), any()); final int [] times = new int[] {0}; if (isDelete) { doAnswer(args -> times[0]++ == 0 ? failureFuture : successFuture).when(writeFn).deleteAsync(any()); } else { doAnswer(args -> times[0]++ == 0 ? failureFuture : successFuture).when(writeFn).putAsync(any(), any()); ArgumentCaptor<String> valCaptor = ArgumentCaptor.forClass(String.class); if (isDelete) { verify(mockWriteFn, times(1)).deleteAsync(keyCaptor.capture()); } else { verify(mockWriteFn, times(retry ? 2 : 1)).putAsync(keyCaptor.capture(), valCaptor.capture());
@Test public void testRetryExhaustedTimePut() throws Exception { String tableId = "testRetryExhaustedTimePut"; TableRetryPolicy policy = new TableRetryPolicy(); policy.withFixedBackoff(Duration.ofMillis(5)); policy.withStopAfterDelay(Duration.ofMillis(100)); TableWriteFunction<String, String> writeFn = mock(TableWriteFunction.class); doReturn(true).when(writeFn).isRetriable(any()); CompletableFuture<String> future = new CompletableFuture(); future.completeExceptionally(new RuntimeException("test exception")); doReturn(future).when(writeFn).deleteAsync(anyString()); RetriableWriteFunction<String, String> retryIO = new RetriableWriteFunction<>(policy, writeFn, schedExec); retryIO.setMetrics(getMetricsUtil(tableId)); try { retryIO.deleteAsync("foo").get(); Assert.fail(); } catch (ExecutionException e) { } // Conservatively: must be at least 3 attempts with 5ms backoff and 100ms maxDelay verify(writeFn, atLeast(3)).deleteAsync(anyString()); Assert.assertTrue(retryIO.retryMetrics.retryCount.getCount() >= 3); Assert.assertEquals(0, retryIO.retryMetrics.successCount.getCount()); Assert.assertTrue(retryIO.retryMetrics.retryTimer.getSnapshot().getMax() > 0); }
doReturn(CompletableFuture.completedFuture(null)).when(writeFn).putAsync(any(), any()); doReturn(CompletableFuture.completedFuture(null)).when(writeFn).putAllAsync(any()); doReturn(CompletableFuture.completedFuture(null)).when(writeFn).deleteAsync(any()); doReturn(CompletableFuture.completedFuture(null)).when(writeFn).deleteAllAsync(any()); AsyncReadWriteTable delegate = new AsyncRemoteTable(readFn, writeFn); verify(writeFn, times(1)).deleteAsync(anyString()); verify(writeRateLimiter, times(1)).throttle(anyString(), anyString()); verify(writeRateLimiter, times(1)).throttleRecords(anyList());
doReturn(CompletableFuture.completedFuture(null)).when(writeFn).putAsync(any(), any()); doReturn(CompletableFuture.completedFuture(null)).when(writeFn).putAllAsync(any()); doReturn(CompletableFuture.completedFuture(null)).when(writeFn).deleteAsync(any()); doReturn(CompletableFuture.completedFuture(null)).when(writeFn).deleteAllAsync(any()); AsyncReadWriteTable delegate = new AsyncRemoteTable(readFn, writeFn); assertEquals(++times, table.writeRetryMetrics.successCount.getCount()); table.deleteAsync("1").get(); verify(writeFn, times(1)).deleteAsync(any()); assertEquals(++times, table.writeRetryMetrics.successCount.getCount()); table.deleteAllAsync(Arrays.asList("1", "2")).get();
doReturn(CompletableFuture.completedFuture(null)).when(writeFn).deleteAsync(any());
doReturn(CompletableFuture.completedFuture(null)).when(writeFn).deleteAsync(any()); cachingTable.deleteAsync("foo").get();