use of com.apple.foundationdb.record.RecordCoreRetriableTransactionException in project fdb-record-layer by FoundationDB.
the class FDBDatabaseRunnerTest method runAsyncRetryNoSuccess.
@Test
public void runAsyncRetryNoSuccess() {
// The rest of the tests retry all of the way, so set guards to make sure they don't take forever.
try (FDBDatabaseRunner runner = database.newRunner()) {
runner.setMaxAttempts(5);
runner.setMaxDelayMillis(100);
runner.setInitialDelayMillis(5);
AtomicInteger iteration = new AtomicInteger(0);
runner.runAsync(context -> {
assertTrue(iteration.get() < runner.getMaxAttempts());
iteration.incrementAndGet();
throw new RecordCoreRetriableTransactionException("Have to try again!", new FDBException("not_committed", 1020));
}).handle((ignore, e) -> {
assertNotNull(e);
assertEquals("Have to try again!", e.getMessage());
assertNotNull(e.getCause());
assertTrue(e.getCause() instanceof FDBException);
assertEquals("not_committed", e.getCause().getMessage());
assertEquals(FDBError.NOT_COMMITTED.code(), ((FDBException) e.getCause()).getCode());
return null;
}).join();
assertEquals(runner.getMaxAttempts(), iteration.get());
}
}
use of com.apple.foundationdb.record.RecordCoreRetriableTransactionException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerSimpleTest method run.
@Test
public void run() {
Index index = runAsyncSetup();
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).setLimit(100).setMaxRetries(3).setRecordsPerSecond(10000).setMdcContext(ImmutableMap.of("mdcKey", "my cool mdc value")).setMaxAttempts(2).build()) {
AtomicInteger attempts = new AtomicInteger();
// Non-FDB error
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new IllegalStateException("illegal state");
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(IllegalStateException.class));
assertEquals("illegal state", e.getMessage());
assertNull(e.getCause());
assertEquals(1, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
// Retriable error that is not in lessen work codes.
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new RecordCoreRetriableTransactionException("Retriable", new FDBException("commit_unknown_result", 1021));
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(RecordCoreRetriableTransactionException.class));
assertEquals("Retriable", e.getMessage());
assertThat(e.getCause(), instanceOf(FDBException.class));
assertEquals("commit_unknown_result", e.getCause().getMessage());
assertEquals(FDBError.COMMIT_UNKNOWN_RESULT.code(), ((FDBException) e.getCause()).getCode());
assertEquals(2, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
// Non-retriable error that is in lessen work codes.
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new RecordCoreException("Non-retriable", new FDBException("transaction_too_large", 2101));
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(RecordCoreException.class));
assertEquals("Non-retriable", e.getMessage());
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(FDBException.class));
assertEquals("transaction_too_large", e.getCause().getMessage());
assertEquals(FDBError.TRANSACTION_TOO_LARGE.code(), ((FDBException) e.getCause()).getCode());
// lessenWorkCodes is maxRetries
assertEquals(4, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
// Retriable error that is in lessen work codes.
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new RecordCoreRetriableTransactionException("Retriable and lessener", new FDBException("not_committed", 1020));
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(RecordCoreRetriableTransactionException.class));
assertEquals("Retriable and lessener", e.getMessage());
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(FDBException.class));
assertEquals("not_committed", e.getCause().getMessage());
assertEquals(FDBError.NOT_COMMITTED.code(), ((FDBException) e.getCause()).getCode());
assertEquals(8, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
}
}
use of com.apple.foundationdb.record.RecordCoreRetriableTransactionException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerSimpleTest method recordsScanned.
@Test
public void recordsScanned() {
Supplier<RuntimeException> nonRetriableException = () -> new RecordCoreException("Non-retriable", new FDBException("transaction_too_large", 2101));
Supplier<RuntimeException> retriableException = () -> new RecordCoreRetriableTransactionException("Retriable", new FDBException("not_committed", 1020));
Queue<Pair<Long, Supplier<RuntimeException>>> queue = new LinkedList<>();
queue.add(Pair.of(0L, retriableException));
queue.add(Pair.of(0L, nonRetriableException));
queue.add(Pair.of(0L, null));
queue.add(Pair.of(1L, null));
queue.add(Pair.of(2L, null));
queue.add(Pair.of(3L, null));
queue.add(Pair.of(4L, retriableException));
queue.add(Pair.of(4L, retriableException));
queue.add(Pair.of(4L, nonRetriableException));
queue.add(Pair.of(4L, nonRetriableException));
queue.add(Pair.of(4L, null));
Index index = runAsyncSetup();
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).setMdcContext(ImmutableMap.of("mdcKey", "my cool mdc value")).setMaxAttempts(3).setConfigLoader(old -> OnlineIndexer.Config.newBuilder().setMaxLimit(100).setMaxRetries(queue.size() + 3).setRecordsPerSecond(10000).setIncreaseLimitAfter(10).setProgressLogIntervalMillis(30).build()).build()) {
AtomicInteger attempts = new AtomicInteger();
attempts.set(0);
AsyncUtil.whileTrue(() -> indexBuilder.buildCommitRetryAsync((store, recordsScanned) -> {
Pair<Long, Supplier<RuntimeException>> behavior = queue.poll();
if (behavior == null) {
return AsyncUtil.READY_FALSE;
} else {
int currentAttempt = attempts.getAndIncrement();
assertEquals(1, recordsScanned.incrementAndGet());
assertEquals(behavior.getLeft().longValue(), indexBuilder.getTotalRecordsScanned(), "Attempt " + currentAttempt);
if (behavior.getRight() != null) {
throw behavior.getRight().get();
}
return AsyncUtil.READY_TRUE;
}
}, Arrays.asList(LogMessageKeys.CALLING_METHOD, "OnlineIndexerTest.recordsScanned"))).join();
assertNull(queue.poll());
assertEquals(5L, indexBuilder.getTotalRecordsScanned());
}
}
use of com.apple.foundationdb.record.RecordCoreRetriableTransactionException in project fdb-record-layer by FoundationDB.
the class FDBReverseDirectoryCache method putIfNotExists.
/**
* Add a new entry to the reverse directory cache if it does not already exist. If an entry already exists
* for the <code>pathString</code> provided, the value for the key in the RDC will be compared against the
* <code>pathValue</code> provided and an <code>IllegalStateException</code> will be thrown if they differ.
* Note that no effort is made to determine if the <code>pathValue</code> actually exists in the directory
* layer itself!
*
* @param context the transaction context in which to do the operation
* @param scopedPathString the name of the entry within the scoped of an FDB directory layer
* @param pathValue the value of the entry that from that FDB directory layer
* @return a future that performs the action
* @throws IllegalStateException if the <code>pathkey</code> provided already exists in the reverse directory
* layer and the <code>pathValue</code> provided does not match that value
*/
public CompletableFuture<Void> putIfNotExists(@Nonnull FDBRecordContext context, @Nonnull ScopedValue<String> scopedPathString, @Nonnull Long pathValue) {
LocatableResolver scope = scopedPathString.getScope();
String pathString = scopedPathString.getData();
String cachedString = context.getDatabase().getReverseDirectoryInMemoryCache().getIfPresent(scope.wrap(pathValue));
if (cachedString != null) {
if (!cachedString.equals(pathString)) {
// newer read version
throw new RecordCoreRetriableTransactionException("Provided value for path key does not match existing value in reverse directory layer in-memory cache").addLogInfo(LogMessageKeys.RESOLVER, scope).addLogInfo(LogMessageKeys.RESOLVER_PATH, pathString).addLogInfo(LogMessageKeys.RESOLVER_KEY, pathValue).addLogInfo(LogMessageKeys.CACHED_KEY, cachedString);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("In-memory cache contains '" + pathString + "' -> '" + pathValue + "' mapping. No need to put");
}
return AsyncUtil.DONE;
}
return getReverseCacheSubspace(scope).thenCompose(subspace -> putToSubspace(context, subspace, scopedPathString, pathValue));
}
Aggregations