@Override public CompletableFuture<Void> putAsync(K key, V value) { Preconditions.checkNotNull(writeFn, "null writeFn"); return writeFn.putAsync(key, value); }
/** * Store single table {@code record} with specified {@code key}. This method must be thread-safe. * The default implementation calls putAsync and blocks on the completion afterwards. * * @param key key for the table record * @param record table record to be written */ default void put(K key, V record) { try { putAsync(key, record).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("PUT failed for " + key, e); } }
/** * Store single table {@code record} with specified {@code key}. This method must be thread-safe. * The default implementation calls putAsync and blocks on the completion afterwards. * * @param key key for the table record * @param record table record to be written */ default void put(K key, V record) { try { putAsync(key, record).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("PUT failed for " + key, e); } }
/** * Store single table {@code record} with specified {@code key}. This method must be thread-safe. * The default implementation calls putAsync and blocks on the completion afterwards. * * @param key key for the table record * @param record table record to be written */ default void put(K key, V record) { try { putAsync(key, record).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("PUT failed for " + key, e); } }
/** * Store single table {@code record} with specified {@code key}. This method must be thread-safe. * The default implementation calls putAsync and blocks on the completion afterwards. * * @param key key for the table record * @param record table record to be written */ default void put(K key, V record) { try { putAsync(key, record).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("PUT failed for " + key, e); } }
/** * Store single table {@code record} with specified {@code key}. This method must be thread-safe. * The default implementation calls putAsync and blocks on the completion afterwards. * * @param key key for the table record * @param record table record to be written */ default void put(K key, V record) { try { putAsync(key, record).get(); } catch (InterruptedException | ExecutionException e) { throw new SamzaException("PUT failed for " + key, e); } }
/** * Asynchronously store the table {@code records} with specified {@code keys}. This method must be thread-safe. * The default implementation calls putAsync for each entry and return a combined future. * @param records table records to be written * @return CompletableFuture for the put request */ default CompletableFuture<Void> putAllAsync(Collection<Entry<K, V>> records) { List<CompletableFuture<Void>> putFutures = records.stream().map(e -> putAsync(e.getKey(), e.getValue())).collect(Collectors.toList()); return CompletableFuture.allOf(Iterables.toArray(putFutures, CompletableFuture.class)); }
/** * Asynchronously store the table {@code records} with specified {@code keys}. This method must be thread-safe. * The default implementation calls putAsync for each entry and return a combined future. * @param records table records to be written * @return CompletableFuture for the put request */ default CompletableFuture<Void> putAllAsync(Collection<Entry<K, V>> records) { List<CompletableFuture<Void>> putFutures = records.stream().map(e -> putAsync(e.getKey(), e.getValue())).collect(Collectors.toList()); return CompletableFuture.allOf(Iterables.toArray(putFutures, CompletableFuture.class)); }
/** * Asynchronously store the table {@code records} with specified {@code keys}. This method must be thread-safe. * The default implementation calls putAsync for each entry and return a combined future. * @param records table records to be written * @return CompletableFuture for the put request */ default CompletableFuture<Void> putAllAsync(Collection<Entry<K, V>> records) { List<CompletableFuture<Void>> putFutures = records.stream().map(e -> putAsync(e.getKey(), e.getValue())).collect(Collectors.toList()); return CompletableFuture.allOf(Iterables.toArray(putFutures, CompletableFuture.class)); }
/** * Asynchronously store the table {@code records} with specified {@code keys}. This method must be thread-safe. * The default implementation calls putAsync for each entry and return a combined future. * @param records table records to be written * @return CompletableFuture for the put request */ default CompletableFuture<Void> putAllAsync(Collection<Entry<K, V>> records) { List<CompletableFuture<Void>> putFutures = records.stream().map(e -> putAsync(e.getKey(), e.getValue())).collect(Collectors.toList()); return CompletableFuture.allOf(Iterables.toArray(putFutures, CompletableFuture.class)); }
/** * Asynchronously store the table {@code records} with specified {@code keys}. This method must be thread-safe. * The default implementation calls putAsync for each entry and return a combined future. * @param records table records to be written * @return CompletableFuture for the put request */ default CompletableFuture<Void> putAllAsync(Collection<Entry<K, V>> records) { List<CompletableFuture<Void>> putFutures = records.stream().map(e -> putAsync(e.getKey(), e.getValue())).collect(Collectors.toList()); return CompletableFuture.allOf(Iterables.toArray(putFutures, CompletableFuture.class)); }
@Override public CompletableFuture<Void> putAsync(K key, V record) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.putAsync(key, record)) .exceptionally(e -> { throw new SamzaException("Failed to get the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> putAsync(K key, V record) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.putAsync(key, record)) .exceptionally(e -> { throw new SamzaException("Failed to get the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> putAsync(K key, V record) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.putAsync(key, record)) .exceptionally(e -> { throw new SamzaException("Failed to get the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> putAsync(K key, V record) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.putAsync(key, record)) .exceptionally(e -> { throw new SamzaException("Failed to get the record for " + key + " after retries.", e); }); }
@Override public CompletableFuture<Void> putAsync(K key, V record) { return failsafe(retryPolicy, retryMetrics, retryExecutor) .future(() -> writeFn.putAsync(key, record)) .exceptionally(e -> { throw new SamzaException("Failed to get the record for " + key + " after retries.", e); }); }
@Test public void testPutAsync() { verifyFailure(() -> roTable.putAsync(1, 2)); rwTable.putAsync(1, 2); verify(writeFn, times(1)).putAsync(any(), any()); }
@Test public void testFirstTimeSuccessPut() throws Exception { String tableId = "testFirstTimeSuccessPut"; TableRetryPolicy policy = new TableRetryPolicy(); policy.withFixedBackoff(Duration.ofMillis(100)); TableWriteFunction<String, String> writeFn = mock(TableWriteFunction.class); doReturn(true).when(writeFn).isRetriable(any()); doReturn(CompletableFuture.completedFuture("bar")).when(writeFn).putAsync(anyString(), anyString()); RetriableWriteFunction<String, String> retryIO = new RetriableWriteFunction<>(policy, writeFn, schedExec); retryIO.setMetrics(getMetricsUtil(tableId)); retryIO.putAsync("foo", "bar").get(); verify(writeFn, times(1)).putAsync(anyString(), anyString()); Assert.assertEquals(0, retryIO.retryMetrics.retryCount.getCount()); Assert.assertEquals(1, retryIO.retryMetrics.successCount.getCount()); Assert.assertEquals(0, retryIO.retryMetrics.retryTimer.getSnapshot().getMax()); }
@Test public void testPutWithRetryDisabled() throws Exception { TableRetryPolicy policy = new TableRetryPolicy(); policy.withFixedBackoff(Duration.ofMillis(10)); policy.withStopAfterDelay(Duration.ofMillis(100)); TableReadFunction<String, String> readFn = mock(TableReadFunction.class); TableWriteFunction<String, String> writeFn = mock(TableWriteFunction.class); doReturn(false).when(writeFn).isRetriable(any()); CompletableFuture<String> future = new CompletableFuture(); future.completeExceptionally(new RuntimeException("test exception")); doReturn(future).when(writeFn).putAsync(any(), any()); AsyncReadWriteTable delegate = new AsyncRemoteTable(readFn, writeFn); AsyncRetriableTable table = new AsyncRetriableTable("t1", delegate, null, policy, schedExec, readFn, writeFn); table.init(TestRemoteTable.getMockContext()); try { table.putAsync("foo", "bar").get(); fail(); } catch (ExecutionException e) { } verify(writeFn, times(1)).putAsync(any(), any()); assertEquals(0, table.writeRetryMetrics.retryCount.getCount()); assertEquals(0, table.writeRetryMetrics.successCount.getCount()); assertEquals(0, table.writeRetryMetrics.permFailureCount.getCount()); assertEquals(0, table.writeRetryMetrics.retryTimer.getSnapshot().getMax()); }
@Test public void testPutWithPermFailureOnTimeout() throws Exception { TableRetryPolicy policy = new TableRetryPolicy(); policy.withFixedBackoff(Duration.ofMillis(5)); policy.withStopAfterDelay(Duration.ofMillis(100)); TableReadFunction<String, String> readFn = mock(TableReadFunction.class); 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(readFn).getAsync(anyString()); AsyncReadWriteTable delegate = new AsyncRemoteTable(readFn, writeFn); AsyncRetriableTable table = new AsyncRetriableTable("t1", delegate, null, policy, schedExec, readFn, writeFn); table.init(TestRemoteTable.getMockContext()); try { table.putAsync("foo", "bar").get(); fail(); } catch (ExecutionException e) { } verify(writeFn, atLeast(3)).putAsync(any(), any()); assertTrue(table.writeRetryMetrics.retryCount.getCount() >= 3); assertEquals(0, table.writeRetryMetrics.successCount.getCount()); assertEquals(1, table.writeRetryMetrics.permFailureCount.getCount()); assertTrue(table.writeRetryMetrics.retryTimer.getSnapshot().getMax() > 0); }