use of com.apple.foundationdb.FDBException in project fdb-record-layer by FoundationDB.
the class FDBDatabaseRunnerTest method runAsyncRetryToSuccess.
@Test
public void runAsyncRetryToSuccess() {
try (FDBDatabaseRunner runner = database.newRunner()) {
AtomicInteger count = new AtomicInteger(0);
String value = runner.runAsync(context -> {
if (count.getAndIncrement() == 0) {
throw new RecordCoreRetriableTransactionException("Have to try again!", new FDBException("not_committed", 1020));
} else {
return CompletableFuture.completedFuture("Success!");
}
}).join();
assertEquals("Success!", value);
assertEquals(2, count.get(), "Should only take one try");
count.set(0);
value = runner.runAsync(context -> {
if (count.getAndIncrement() == 0) {
throw new FDBException("not_committed", 1020);
} else {
return CompletableFuture.completedFuture("Success!");
}
}).join();
assertEquals("Success!", value);
assertEquals(2, count.get(), "Should only take one try");
count.set(0);
value = runner.runAsync(context -> {
if (count.getAndIncrement() == 0) {
throw new RecordCoreRetriableTransactionException("Something non-standard");
} else {
return CompletableFuture.completedFuture("Success!");
}
}).join();
assertEquals("Success!", value);
assertEquals(2, count.get(), "Should only take one try");
value = runner.runAsync(context -> CompletableFuture.completedFuture("Success!")).join();
assertEquals("Success!", value);
}
}
use of com.apple.foundationdb.FDBException in project fdb-record-layer by FoundationDB.
the class AutoContinuingCursorTest method testRetryableMaxAttempts.
@Test
void testRetryableMaxAttempts() {
final AtomicInteger exceptionCount = new AtomicInteger(0);
CompletionException e = assertThrows(CompletionException.class, () -> testAutoContinuingCursorGivenCursorGenerator((context, continuation) -> new TestingListCursor<>(list, continuation, () -> {
exceptionCount.incrementAndGet();
CompletableFuture<Void> failedFuture = new CompletableFuture<>();
failedFuture.completeExceptionally(new FDBException("transaction_too_old", FDBError.TRANSACTION_TOO_OLD.code()));
return failedFuture;
}), 3, list));
assertTrue(e.getMessage().contains("transaction_too_old"));
// We requested at most 3 retries on a retriable exception, so the fourth exception thrown
// was the one that caused the cursor to abort.
assertEquals(exceptionCount.get(), 4);
}
use of com.apple.foundationdb.FDBException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerSimpleTest method lessenLimits.
@Test
public void lessenLimits() {
Index index = runAsyncSetup();
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).setLimit(100).setMaxRetries(30).setRecordsPerSecond(10000).setMdcContext(ImmutableMap.of("mdcKey", "my cool mdc value")).setMaxAttempts(3).build()) {
AtomicInteger attempts = new AtomicInteger();
AtomicInteger limit = new AtomicInteger(100);
// Non-retriable error that is in lessen work codes.
attempts.set(0);
indexBuilder.buildCommitRetryAsync((store, recordsScanned) -> {
assertEquals(attempts.getAndIncrement(), indexBuilder.getLimit(), limit.getAndUpdate(x -> Math.max(x, (3 * x) / 4)));
throw new RecordCoreException("Non-retriable", new FDBException("transaction_too_large", 2101));
}, null).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(RecordCoreException.class));
assertEquals("Non-retriable", e.getMessage());
return null;
}).join();
assertEquals(31, attempts.get());
}
}
use of com.apple.foundationdb.FDBException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerUniqueIndexTest method uniquenessViolations.
@Test
public void uniquenessViolations() {
List<TestRecords1Proto.MySimpleRecord> records = LongStream.range(0, 10).mapToObj(val -> TestRecords1Proto.MySimpleRecord.newBuilder().setRecNo(val).setNumValue2(((int) val) % 5).build()).collect(Collectors.toList());
Index index = new Index("simple$value_2", field("num_value_2"), EmptyKeyExpression.EMPTY, IndexTypes.VALUE, IndexOptions.UNIQUE_OPTIONS);
FDBRecordStoreTestBase.RecordMetaDataHook hook = metaDataBuilder -> metaDataBuilder.addIndex("MySimpleRecord", index);
// Case 1: Entirely in build.
openSimpleMetaData();
try (FDBRecordContext context = openContext()) {
records.forEach(recordStore::saveRecord);
context.commit();
}
openSimpleMetaData(hook);
try (FDBRecordContext context = openContext()) {
recordStore.markIndexWriteOnly(index).join();
context.commit();
}
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).build()) {
indexBuilder.buildIndexAsync().handle((ignore, e) -> {
assertNotNull(e);
RuntimeException runE = FDBExceptions.wrapException(e);
assertNotNull(runE);
assertThat(runE, instanceOf(RecordIndexUniquenessViolation.class));
return null;
}).join();
// Case 2: While in write-only mode.
try (FDBRecordContext context = openContext()) {
recordStore.deleteAllRecords();
recordStore.markIndexWriteOnly(index).join();
context.commit();
}
try (FDBRecordContext context = openContext()) {
records.forEach(recordStore::saveRecord);
context.commit();
}
try (FDBRecordContext context = openContext()) {
assertEquals(10, (int) recordStore.scanUniquenessViolations(index).getCount().join());
context.commit();
}
indexBuilder.buildIndexAsync().handle((ignore, e) -> {
assertNotNull(e);
RuntimeException runE = FDBExceptions.wrapException(e);
assertNotNull(runE);
assertThat(runE, instanceOf(RecordIndexUniquenessViolation.class));
return null;
}).join();
}
// Case 3: Some in write-only mode.
fdb.run(context -> {
FDBRecordStore.deleteStore(context, subspace);
return null;
});
openSimpleMetaData();
try (FDBRecordContext context = openContext()) {
for (int i = 0; i < 5; i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
openSimpleMetaData(hook);
try (FDBRecordContext context = openContext()) {
recordStore.markIndexWriteOnly(index).join();
for (int i = 5; i < records.size(); i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).build()) {
indexBuilder.buildIndexAsync().handle((ignore, e) -> {
assertNotNull(e);
RuntimeException runE = FDBExceptions.wrapException(e);
assertNotNull(runE);
assertThat(runE, instanceOf(RecordIndexUniquenessViolation.class));
return null;
}).join();
}
// Case 4: Some in write-only mode with an initial range build that shouldn't affect anything.
fdb.run(context -> {
FDBRecordStore.deleteStore(context, subspace);
return null;
});
openSimpleMetaData();
try (FDBRecordContext context = openContext()) {
for (int i = 5; i < records.size(); i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
openSimpleMetaData(hook);
try (FDBRecordContext context = openContext()) {
recordStore.markIndexWriteOnly(index).join();
for (int i = 0; i < 5; i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).build()) {
indexBuilder.buildUnbuiltRange(Key.Evaluated.scalar(0L), Key.Evaluated.scalar(5L)).join();
try (FDBRecordContext context = openContext()) {
assertEquals(0, (int) recordStore.scanUniquenessViolations(index).getCount().join());
context.commit();
}
indexBuilder.buildUnbuiltRange(Key.Evaluated.scalar(5L), Key.Evaluated.scalar(10L)).join();
try (FDBRecordContext context = openContext()) {
assertEquals(10, (int) recordStore.scanUniquenessViolations(index).getCount().join());
context.commit();
}
indexBuilder.buildIndexAsync().handle((ignore, e) -> {
assertNotNull(e);
RuntimeException runE = FDBExceptions.wrapException(e);
assertNotNull(runE);
assertThat(runE, instanceOf(RecordIndexUniquenessViolation.class));
return null;
}).join();
}
// Case 5: Should be caught by write-only writes after build.
fdb.run(context -> {
FDBRecordStore.deleteStore(context, subspace);
return null;
});
openSimpleMetaData();
try (FDBRecordContext context = openContext()) {
for (int i = 0; i < 5; i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
openSimpleMetaData(hook);
try (FDBRecordContext context = openContext()) {
recordStore.markIndexWriteOnly(index).join();
context.commit();
}
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).build()) {
indexBuilder.buildIndex();
}
try (FDBRecordContext context = openContext()) {
for (int i = 5; i < records.size(); i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
fail("Did not catch uniqueness violation when done after build by write-only writes");
} catch (RecordIndexUniquenessViolation e) {
// passed.
}
// Case 6: Should be caught by write-only writes after partial build.
fdb.run(context -> {
FDBRecordStore.deleteStore(context, subspace);
return null;
});
openSimpleMetaData();
try (FDBRecordContext context = openContext()) {
for (int i = 0; i < 5; i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
openSimpleMetaData(hook);
try (FDBRecordContext context = openContext()) {
recordStore.markIndexWriteOnly(index).join();
context.commit();
}
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).build()) {
indexBuilder.buildUnbuiltRange(Key.Evaluated.scalar(0L), Key.Evaluated.scalar(5L)).join();
try (FDBRecordContext context = openContext()) {
for (int i = 5; i < records.size(); i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
try (FDBRecordContext context = openContext()) {
assertEquals(10, (int) recordStore.scanUniquenessViolations(index).getCount().join());
context.commit();
}
indexBuilder.buildIndexAsync().handle((ignore, e) -> {
assertNotNull(e);
RuntimeException runE = FDBExceptions.wrapException(e);
assertNotNull(runE);
assertThat(runE, instanceOf(RecordIndexUniquenessViolation.class));
return null;
}).join();
}
// Case 7: The second of these two transactions should fail on not_committed, and then
// there should be a uniqueness violation.
fdb.run(context -> {
FDBRecordStore.deleteStore(context, subspace);
return null;
});
openSimpleMetaData();
try (FDBRecordContext context = openContext()) {
for (int i = 0; i < 5; i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
openSimpleMetaData(hook);
try (FDBRecordContext context = openContext()) {
recordStore.markIndexWriteOnly(index).join();
context.commit();
}
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).build()) {
try (FDBRecordContext context = openContext()) {
context.getReadVersion();
try (FDBRecordContext context2 = fdb.openContext()) {
context2.getReadVersion();
FDBRecordStore recordStore2 = recordStore.asBuilder().setContext(context2).build();
indexBuilder.buildUnbuiltRange(recordStore, null, Key.Evaluated.scalar(5L)).join();
recordStore2.saveRecord(records.get(8));
context.commit();
context2.commitAsync().handle((ignore, e) -> {
assertNotNull(e);
RuntimeException runE = FDBExceptions.wrapException(e);
assertThat(runE, instanceOf(RecordCoreRetriableTransactionException.class));
assertNotNull(runE.getCause());
assertThat(runE.getCause(), instanceOf(FDBException.class));
FDBException fdbE = (FDBException) runE.getCause();
assertEquals(FDBError.NOT_COMMITTED.code(), fdbE.getCode());
return null;
}).join();
}
}
try (FDBRecordContext context = openContext()) {
for (int i = 5; i < records.size(); i++) {
recordStore.saveRecord(records.get(i));
}
context.commit();
}
try (FDBRecordContext context = openContext()) {
assertEquals(10, (int) recordStore.scanUniquenessViolations(index).getCount().join());
context.commit();
}
indexBuilder.buildIndexAsync().handle((ignore, e) -> {
assertNotNull(e);
RuntimeException runE = FDBExceptions.wrapException(e);
assertNotNull(runE);
assertThat(runE, instanceOf(RecordIndexUniquenessViolation.class));
return null;
}).join();
}
}
use of com.apple.foundationdb.FDBException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerSimpleTest method reincreaseLimit.
@Test
public void reincreaseLimit() {
// Non-retriable error that is in lessen work codes.
Supplier<RuntimeException> createException = () -> new RecordCoreException("Non-retriable", new FDBException("transaction_too_large", 2101));
Queue<Pair<Integer, Supplier<RuntimeException>>> queue = new LinkedList<>();
// failures until it hits 1
for (int i = 100; i > 1; i = (3 * i) / 4) {
queue.add(Pair.of(i, createException));
}
// success for a while
for (int i = 0; i < 10; i++) {
queue.add(Pair.of(1, null));
}
// queue size = 23
// now starts re-increasing
queue.add(Pair.of(2, null));
queue.add(Pair.of(3, null));
queue.add(Pair.of(4, null));
for (int i = 5; i < 100; i = (i * 4) / 3) {
queue.add(Pair.of(i, null));
}
// queue size = 38
// does not pass original max
queue.add(Pair.of(100, null));
queue.add(Pair.of(100, null));
queue.add(Pair.of(100, null));
for (int i = 100; i > 42; i = (3 * i) / 4) {
queue.add(Pair.of(i, createException));
}
// success for a while
for (int i = 0; i < 10; i++) {
queue.add(Pair.of(42, null));
}
// queue size = 54
// fail once
queue.add(Pair.of(56, createException));
for (int i = 0; i < 10; i++) {
queue.add(Pair.of(42, null));
}
// queue size = 65
queue.add(Pair.of(56, createException));
queue.add(Pair.of(42, null));
reincreaseLimit(queue, index -> OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).setLimit(100).setMaxRetries(queue.size() + 3).setRecordsPerSecond(10000).setIncreaseLimitAfter(10).setMdcContext(ImmutableMap.of("mdcKey", "my cool mdc value")).setMaxAttempts(3).setProgressLogIntervalMillis(0).build());
}
Aggregations