use of com.apple.foundationdb.record.cursors.FirableCursor in project fdb-record-layer by FoundationDB.
the class RecordCursorTest method mapPipelinedErrorAtConcurrentCompletion.
/**
* Test that when the outer cursor and an inner future complete "at the same time" (as close as we can) that the
* error is propagated.
*
* @throws ExecutionException from futures joined in the test
* @throws InterruptedException from futures joined in the test
*/
@Test
public void mapPipelinedErrorAtConcurrentCompletion() throws ExecutionException, InterruptedException {
final RuntimeException runtimeEx = new RuntimeException("some random exception");
List<CompletableFuture<Integer>> futures = Arrays.asList(new CompletableFuture<>(), new CompletableFuture<>(), new CompletableFuture<>());
FirableCursor<Integer> firableCursor = new FirableCursor<>(RecordCursor.fromList(Arrays.asList(0, 1, 2)));
RecordCursor<Integer> cursor = firableCursor.mapPipelined(futures::get, 2);
CompletableFuture<RecordCursorResult<Integer>> resultFuture = cursor.onNext();
assertFalse(resultFuture.isDone());
firableCursor.fire();
assertFalse(resultFuture.isDone());
futures.get(0).complete(1066);
RecordCursorResult<Integer> result = resultFuture.get();
assertTrue(result.hasNext());
assertEquals(1066, (int) result.get());
// The (non-exceptional) firable cursor completes at "the same time" as the exceptional inner result.
CompletableFuture<RecordCursorResult<Integer>> secondResultFuture = cursor.onNext();
assertFalse(secondResultFuture.isDone());
firableCursor.fire();
assertFalse(secondResultFuture.isDone());
firableCursor.fire();
futures.get(1).completeExceptionally(runtimeEx);
ExecutionException executionEx = assertThrows(ExecutionException.class, secondResultFuture::get);
assertNotNull(executionEx.getCause());
assertEquals(runtimeEx, executionEx.getCause());
// Should get the same exception again
executionEx = assertThrows(ExecutionException.class, () -> cursor.onNext().get());
assertEquals(runtimeEx, executionEx.getCause());
}
use of com.apple.foundationdb.record.cursors.FirableCursor in project fdb-record-layer by FoundationDB.
the class UnorderedUnionCursorTest method loopIterationWithLimit.
@Test
public void loopIterationWithLimit() throws ExecutionException, InterruptedException {
FDBStoreTimer timer = new FDBStoreTimer();
FirableCursor<Integer> secondCursor = new FirableCursor<>(RecordCursor.fromList(Arrays.asList(3, 4)));
RecordCursor<Integer> cursor = UnorderedUnionCursor.create(Arrays.asList(continuation -> RecordCursor.fromList(Arrays.asList(1, 2), continuation).limitRowsTo(1), continuation -> secondCursor), null, timer);
RecordCursorResult<Integer> cursorResult = cursor.getNext();
assertEquals(1, (int) cursorResult.get());
CompletableFuture<RecordCursorResult<Integer>> cursorResultFuture = cursor.onNext();
assertFalse(cursorResultFuture.isDone());
secondCursor.fire();
cursorResult = cursorResultFuture.get();
assertEquals(3, (int) cursorResult.get());
cursorResultFuture = cursor.onNext();
assertFalse(cursorResultFuture.isDone());
secondCursor.fire();
cursorResult = cursorResultFuture.get();
assertEquals(4, (int) cursorResult.get());
cursorResultFuture = cursor.onNext();
assertFalse(cursorResultFuture.isDone());
secondCursor.fire();
cursorResult = cursorResultFuture.get();
assertFalse(cursorResult.hasNext());
assertEquals(RecordCursor.NoNextReason.RETURN_LIMIT_REACHED, cursorResult.getNoNextReason());
assertThat(timer.getCount(FDBStoreTimer.Events.QUERY_INTERSECTION), lessThanOrEqualTo(5));
}
use of com.apple.foundationdb.record.cursors.FirableCursor in project fdb-record-layer by FoundationDB.
the class RecordCursorTest method flatMapPipelineErrorPropagation.
@Test
public void flatMapPipelineErrorPropagation() throws ExecutionException, InterruptedException {
FirableCursor<String> firableCursor1 = new FirableCursor<>(RecordCursor.fromList(Collections.singletonList("hello")));
FirableCursor<String> firableCursor2 = new FirableCursor<>(new BrokenCursor());
List<FirableCursor<String>> firableCursors = Arrays.asList(firableCursor1, firableCursor2);
FirableCursor<Integer> outerCursor = new FirableCursor<>(RecordCursor.fromList(Arrays.asList(0, 1)));
RecordCursor<String> cursor = RecordCursor.flatMapPipelined(cont -> outerCursor, (a, cont) -> firableCursors.get(a), null, 10);
outerCursor.fire();
firableCursor1.fire();
RecordCursorResult<String> cursorResult = cursor.onNext().get();
assertTrue(cursorResult.hasNext());
assertEquals("hello", cursorResult.get());
CompletableFuture<RecordCursorResult<String>> nextResultFuture = cursor.onNext();
firableCursor1.fire();
assertFalse(nextResultFuture.isDone());
outerCursor.fire();
firableCursor2.fire();
ExecutionException e = assertThrows(ExecutionException.class, nextResultFuture::get);
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(RuntimeException.class));
assertEquals("sorry", e.getCause().getMessage());
RecordCursor<Integer> outerCursorError = RecordCursor.flatMapPipelined(cont -> new BrokenCursor(), (s, cont) -> RecordCursor.fromList(Collections.singletonList(s.length())), null, 10);
e = assertThrows(ExecutionException.class, () -> outerCursorError.onNext().get());
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(RuntimeException.class));
assertEquals("sorry", e.getCause().getMessage());
}
use of com.apple.foundationdb.record.cursors.FirableCursor in project fdb-record-layer by FoundationDB.
the class ProbableIntersectionCursorTest method basicIntersection.
/**
* Show that a basic intersection succeeds.
*/
@Test
public void basicIntersection() {
final FDBStoreTimer timer = new FDBStoreTimer();
final Iterator<Integer> iterator1 = IntStream.iterate(0, x -> x + 2).limit(150).iterator();
final Iterator<Integer> iterator2 = IntStream.iterate(0, x -> x + 3).limit(100).iterator();
final FirableCursor<Integer> cursor1 = new FirableCursor<>(RecordCursor.fromIterator(iterator1));
final FirableCursor<Integer> cursor2 = new FirableCursor<>(RecordCursor.fromIterator(iterator2));
final RecordCursor<Integer> intersectionCursor = ProbableIntersectionCursor.create(Collections::singletonList, Arrays.asList(bignore -> cursor1, bignore -> cursor2), null, timer);
// Intersection consumes first cursor
cursor1.fireAll();
CompletableFuture<RecordCursorResult<Integer>> firstFuture = intersectionCursor.onNext();
cursor2.fire();
RecordCursorResult<Integer> firstResult = firstFuture.join();
assertEquals(0, (int) firstResult.get());
assertThat(firstResult.hasNext(), is(true));
assertEquals(cursor1.getNext().getNoNextReason(), RecordCursor.NoNextReason.SOURCE_EXHAUSTED);
// Intersection consumes second cursor as they come
cursor2.fireAll();
AtomicInteger falsePositives = new AtomicInteger();
AsyncUtil.whileTrue(() -> intersectionCursor.onNext().thenApply(result -> {
if (result.hasNext()) {
int value = result.get();
// every result *must* be divisible by 3
assertEquals(0, value % 3);
if (value % 2 != 0) {
// most results should be divisible by 2
falsePositives.incrementAndGet();
}
assertThat(result.getContinuation().isEnd(), is(false));
assertNotNull(result.getContinuation().toBytes());
try {
RecordCursorProto.ProbableIntersectionContinuation protoContinuation = RecordCursorProto.ProbableIntersectionContinuation.parseFrom(result.getContinuation().toBytes());
assertEquals(2, protoContinuation.getChildStateCount());
assertThat(protoContinuation.getChildState(0).getExhausted(), is(true));
assertThat(protoContinuation.getChildState(0).hasContinuation(), is(false));
assertThat(protoContinuation.getChildState(1).getExhausted(), is(false));
assertThat(protoContinuation.getChildState(1).hasContinuation(), is(true));
} catch (InvalidProtocolBufferException e) {
throw new RecordCoreException("error parsing proto continuation", e);
}
} else {
assertThat(result.getNoNextReason().isSourceExhausted(), is(true));
assertThat(result.getContinuation().isEnd(), is(true));
assertNull(result.getContinuation().toBytes());
}
return result.hasNext();
}), intersectionCursor.getExecutor()).join();
assertThat(falsePositives.get(), lessThan(5));
assertEquals(50 + falsePositives.get(), timer.getCount(FDBStoreTimer.Counts.QUERY_INTERSECTION_PLAN_MATCHES));
assertEquals(200 - falsePositives.get(), timer.getCount(FDBStoreTimer.Counts.QUERY_INTERSECTION_PLAN_NONMATCHES));
}
use of com.apple.foundationdb.record.cursors.FirableCursor in project fdb-record-layer by FoundationDB.
the class ProbableIntersectionCursorTest method loopIterationWithLimit.
@Test
public void loopIterationWithLimit() throws ExecutionException, InterruptedException {
FDBStoreTimer timer = new FDBStoreTimer();
FirableCursor<Integer> secondCursor = new FirableCursor<>(RecordCursor.fromList(Arrays.asList(2, 1)));
RecordCursor<Integer> cursor = ProbableIntersectionCursor.create(Collections::singletonList, Arrays.asList(continuation -> RecordCursor.fromList(Arrays.asList(1, 2), continuation).limitRowsTo(1), continuation -> secondCursor), null, timer);
CompletableFuture<RecordCursorResult<Integer>> cursorResultFuture = cursor.onNext();
secondCursor.fire();
assertFalse(cursorResultFuture.isDone());
secondCursor.fire();
RecordCursorResult<Integer> cursorResult = cursorResultFuture.get();
assertEquals(1, (int) cursorResult.get());
secondCursor.fire();
cursorResult = cursor.getNext();
assertEquals(RecordCursor.NoNextReason.RETURN_LIMIT_REACHED, cursorResult.getNoNextReason());
assertThat(timer.getCount(FDBStoreTimer.Events.QUERY_INTERSECTION), lessThanOrEqualTo(5));
}
Aggregations