/** * Alternate method of committing, for use with {@code try-with-resources}. */ @Override public void close() { commit(); }
/** * Collect {@code <T>} into a buffer, and invoke the given callback whenever * the buffer is full, during an explicit commit, or on close. */ public static <T> BatchingCallback<T> batchInto(int size, Callback<? super List<T>> out) { return new BatchingCallback<T>(size, out); }
/** * Explicitly flush the buffer, even if it is not full. * @return true if the flush succeeds, false if the delegate throws {@code CallbackRefusedException} */ public boolean commit() { try { commitInternal(); return true; } catch (CallbackRefusedException e) { return false; } }
@Test public void testGood() throws Exception { ExecutorService executor = MoreExecutors.sameThreadExecutor(); CallbackCollector<List<String>> out = new CallbackCollector<>(); BatchingCallback<String> batcher = BatchingCallback.batchInto(2, executor, out, false); batcher.call("a"); batcher.call("b"); batcher.call("c"); batcher.call("d"); batcher.call("e"); batcher.commit(); assertEquals(of(of("a", "b"), of("c", "d"), of("e")), out.getItems()); }
@Test(expected=BatchingCallbackExecutionException.class) public void testSingleExceptionFails() throws Exception { ExecutorService executor = Executors.newSingleThreadExecutor(); try { Callback<List<String>> out = new Callback<List<String>>() { @Override public void call(List<String> item) throws Exception { Thread.sleep(10); throw new IllegalStateException("boom!"); } }; BatchingCallback<String> batcher = BatchingCallback.batchInto(2, executor, out, true); batcher.call("a"); batcher.close(); } finally { executor.shutdownNow(); } } }
BatchingCallback<String> batcher = BatchingCallback.batchInto(2, executor, out, true); batcher.call("a"); batcher.call("b"); try { batcher.call("c"); fail(); } catch (BatchingCallbackExecutionException bcee) { batcher.call("d"); batcher.call("e"); batcher.call("f"); fail(); } catch (CallbackRefusedException e) {
@Test public void testCallbackRefused() throws Exception { final List<Collection<String>> items = Lists.newArrayList(); Callback<Collection<String>> callback = new Callback<Collection<String>>() { @Override public void call(Collection<String> item) throws Exception { if (items.size() > 1) { throw new CallbackRefusedException(); } items.add(item); } }; try (BatchingCallback<String> batcher = BatchingCallback.<String>batchInto(2, callback)) { Callbacks.stream(batcher, "a", "b", "c", "d", "e", "f", "g"); } assertEquals(of( of("a", "b"), of("c", "d") ), items); } }
@Test public void testBatchingCallback() throws Exception { CallbackCollector<List<String>> collector = new CallbackCollector<>(); try (BatchingCallback<String> batcher = BatchingCallback.batchInto(2, collector)) { batcher.call("a"); batcher.call("b"); batcher.call("c"); batcher.commit(); batcher.call("d"); batcher.call("e"); batcher.call("f"); } assertEquals(of( of("a", "b"), of("c"), of("d", "e"), of("f") ), collector.getItems()); }
@Override public boolean commit() { boolean result = super.commit(); ExecutorCallback.class.cast(getOut()).close(); return result; }
/** * Add an item to the buffer. May cause a commit if the buffer is full. * @throws CallbackRefusedException if the delegate throws. */ @Override public void call(T item) throws CallbackRefusedException { while (!list.offer(item)) { commitInternal(); } }