use of com.mongodb.internal.async.function.RetryState in project mongo-java-driver by mongodb.
the class CommandOperationHelper method executeRetryableWrite.
static <T, R> R executeRetryableWrite(final WriteBinding binding, final String database, final ReadPreference readPreference, final FieldNameValidator fieldNameValidator, final Decoder<T> commandResultDecoder, final CommandCreator commandCreator, final CommandWriteTransformer<T, R> transformer, final Function<BsonDocument, BsonDocument> retryCommandModifier) {
RetryState retryState = initialRetryState(true);
Supplier<R> retryingWrite = decorateWriteWithRetries(retryState, () -> {
logRetryExecute(retryState);
boolean firstAttempt = retryState.isFirstAttempt();
if (!firstAttempt && binding.getSessionContext().hasActiveTransaction()) {
binding.getSessionContext().clearTransactionContext();
}
return withSourceAndConnection(binding::getWriteConnectionSource, true, (source, connection) -> {
int maxWireVersion = connection.getDescription().getMaxWireVersion();
try {
retryState.breakAndThrowIfRetryAnd(() -> !canRetryWrite(source.getServerDescription(), connection.getDescription(), binding.getSessionContext()));
BsonDocument command = retryState.attachment(AttachmentKeys.command()).map(previousAttemptCommand -> {
assertFalse(firstAttempt);
return retryCommandModifier.apply(previousAttemptCommand);
}).orElseGet(() -> commandCreator.create(source.getServerDescription(), connection.getDescription()));
// attach `maxWireVersion`, `retryableCommandFlag` ASAP because they are used to check whether we should retry
retryState.attach(AttachmentKeys.maxWireVersion(), maxWireVersion, true).attach(AttachmentKeys.retryableCommandFlag(), isRetryWritesEnabled(command), true).attach(AttachmentKeys.commandDescriptionSupplier(), command::getFirstKey, true).attach(AttachmentKeys.command(), command, false);
logRetryExecute(retryState);
return transformer.apply(connection.command(database, command, fieldNameValidator, readPreference, commandResultDecoder, binding.getSessionContext(), binding.getServerApi(), binding.getRequestContext()), connection);
} catch (MongoException e) {
if (!firstAttempt) {
addRetryableWriteErrorLabel(e, maxWireVersion);
}
throw e;
}
});
});
try {
return retryingWrite.get();
} catch (MongoException e) {
throw transformWriteException(e);
}
}
use of com.mongodb.internal.async.function.RetryState in project mongo-java-driver by mongodb.
the class CommandOperationHelper method executeRetryableRead.
static <D, T> T executeRetryableRead(final ReadBinding binding, final Supplier<ConnectionSource> readConnectionSourceSupplier, final String database, final CommandCreator commandCreator, final Decoder<D> decoder, final CommandReadTransformer<D, T> transformer, final boolean retryReads) {
RetryState retryState = initialRetryState(retryReads);
Supplier<T> read = decorateReadWithRetries(retryState, () -> {
logRetryExecute(retryState);
return withSourceAndConnection(readConnectionSourceSupplier, false, (source, connection) -> {
retryState.breakAndThrowIfRetryAnd(() -> !canRetryRead(source.getServerDescription(), connection.getDescription(), binding.getSessionContext()));
return createReadCommandAndExecute(retryState, binding, source, database, commandCreator, decoder, transformer, connection);
});
});
return read.get();
}
use of com.mongodb.internal.async.function.RetryState in project mongo-java-driver by mongodb.
the class CommandOperationHelper method executeRetryableReadAsync.
static <D, T> void executeRetryableReadAsync(final AsyncReadBinding binding, final AsyncCallbackSupplier<AsyncConnectionSource> sourceAsyncSupplier, final String database, final CommandCreator commandCreator, final Decoder<D> decoder, final CommandReadTransformerAsync<D, T> transformer, final boolean retryReads, final SingleResultCallback<T> callback) {
RetryState retryState = initialRetryState(retryReads);
binding.retain();
AsyncCallbackSupplier<T> asyncRead = CommandOperationHelper.<T>decorateReadWithRetries(retryState, funcCallback -> {
logRetryExecute(retryState);
withAsyncSourceAndConnection(sourceAsyncSupplier, false, funcCallback, (source, connection, releasingCallback) -> {
if (retryState.breakAndCompleteIfRetryAnd(() -> !canRetryRead(source.getServerDescription(), connection.getDescription(), binding.getSessionContext()), releasingCallback)) {
return;
}
createReadCommandAndExecuteAsync(retryState, binding, source, database, commandCreator, decoder, transformer, connection, releasingCallback);
});
}).whenComplete(binding::release);
asyncRead.get(errorHandlingCallback(callback, LOGGER));
}
use of com.mongodb.internal.async.function.RetryState in project mongo-java-driver by mongodb.
the class ListCollectionsOperation method execute.
@Override
public BatchCursor<T> execute(final ReadBinding binding) {
RetryState retryState = initialRetryState(retryReads);
Supplier<BatchCursor<T>> read = decorateReadWithRetries(retryState, () -> {
logRetryExecute(retryState);
return withSourceAndConnection(binding::getReadConnectionSource, false, (source, connection) -> {
retryState.breakAndThrowIfRetryAnd(() -> !canRetryRead(source.getServerDescription(), connection.getDescription(), binding.getSessionContext()));
if (serverIsAtLeastVersionThreeDotZero(connection.getDescription())) {
try {
return createReadCommandAndExecute(retryState, binding, source, databaseName, getCommandCreator(), createCommandDecoder(), commandTransformer(), connection);
} catch (MongoCommandException e) {
return rethrowIfNotNamespaceError(e, createEmptyBatchCursor(createNamespace(), decoder, source.getServerDescription().getAddress(), batchSize));
}
} else {
retryState.markAsLastAttempt();
return new ProjectingBatchCursor(new QueryBatchCursor<>(connection.query(getNamespace(), asQueryDocument(connection.getDescription(), binding.getReadPreference()), null, 0, 0, batchSize, binding.getReadPreference().isSecondaryOk(), false, false, false, false, false, new BsonDocumentCodec(), binding.getRequestContext()), 0, batchSize, new BsonDocumentCodec(), source));
}
});
});
return read.get();
}
use of com.mongodb.internal.async.function.RetryState in project mongo-java-driver by mongodb.
the class ListCollectionsOperation method executeAsync.
@Override
public void executeAsync(final AsyncReadBinding binding, final SingleResultCallback<AsyncBatchCursor<T>> callback) {
RetryState retryState = initialRetryState(retryReads);
binding.retain();
AsyncCallbackSupplier<AsyncBatchCursor<T>> asyncRead = CommandOperationHelper.<AsyncBatchCursor<T>>decorateReadWithRetries(retryState, funcCallback -> {
logRetryExecute(retryState);
withAsyncSourceAndConnection(binding::getReadConnectionSource, false, funcCallback, (source, connection, releasingCallback) -> {
if (retryState.breakAndCompleteIfRetryAnd(() -> !canRetryRead(source.getServerDescription(), connection.getDescription(), binding.getSessionContext()), releasingCallback)) {
return;
}
if (serverIsAtLeastVersionThreeDotZero(connection.getDescription())) {
createReadCommandAndExecuteAsync(retryState, binding, source, databaseName, getCommandCreator(), createCommandDecoder(), asyncTransformer(), connection, (result, t) -> {
if (t != null && !isNamespaceError(t)) {
releasingCallback.onResult(null, t);
} else {
releasingCallback.onResult(result != null ? result : emptyAsyncCursor(source), null);
}
});
} else {
retryState.markAsLastAttempt();
connection.queryAsync(getNamespace(), asQueryDocument(connection.getDescription(), binding.getReadPreference()), null, 0, 0, batchSize, binding.getReadPreference().isSecondaryOk(), false, false, false, false, false, new BsonDocumentCodec(), binding.getRequestContext(), new SingleResultCallback<QueryResult<BsonDocument>>() {
@Override
public void onResult(final QueryResult<BsonDocument> result, final Throwable t) {
if (t != null) {
releasingCallback.onResult(null, t);
} else {
releasingCallback.onResult(new ProjectingAsyncBatchCursor(new AsyncQueryBatchCursor<BsonDocument>(result, 0, batchSize, 0, new BsonDocumentCodec(), source, connection)), null);
}
}
});
}
});
}).whenComplete(binding::release);
asyncRead.get(errorHandlingCallback(callback, LOGGER));
}
Aggregations