Search in sources :

Example 1 with MongoWriteConcernWithResponseException

use of com.mongodb.internal.connection.MongoWriteConcernWithResponseException in project mongo-java-driver by mongodb.

the class MixedBulkWriteOperation method executeBulkWriteBatch.

private BulkWriteResult executeBulkWriteBatch(final RetryState retryState, final WriteBinding binding, final Connection connection, final int maxWireVersion) {
    BulkWriteTracker currentBulkWriteTracker = retryState.attachment(AttachmentKeys.bulkWriteTracker()).orElseThrow(Assertions::fail);
    BulkWriteBatch currentBatch = currentBulkWriteTracker.batch().orElseThrow(Assertions::fail);
    while (currentBatch.shouldProcessBatch()) {
        try {
            BsonDocument result = executeCommand(connection, currentBatch, binding);
            if (currentBatch.getRetryWrites() && !binding.getSessionContext().hasActiveTransaction()) {
                MongoException writeConcernBasedError = ProtocolHelper.createSpecialException(result, connection.getDescription().getServerAddress(), "errMsg");
                if (writeConcernBasedError != null) {
                    if (currentBulkWriteTracker.lastAttempt()) {
                        addRetryableWriteErrorLabel(writeConcernBasedError, maxWireVersion);
                        addErrorLabelsToWriteConcern(result.getDocument("writeConcernError"), writeConcernBasedError.getErrorLabels());
                    } else if (CommandOperationHelper.shouldAttemptToRetryWrite(retryState, writeConcernBasedError)) {
                        throw new MongoWriteConcernWithResponseException(writeConcernBasedError, result);
                    }
                }
            }
            currentBatch.addResult(result);
            currentBulkWriteTracker = BulkWriteTracker.attachNext(retryState, currentBatch);
            currentBatch = currentBulkWriteTracker.batch().orElseThrow(Assertions::fail);
        } catch (MongoException exception) {
            if (!(retryState.isFirstAttempt() || (exception instanceof MongoWriteConcernWithResponseException))) {
                addRetryableWriteErrorLabel(exception, maxWireVersion);
            }
            throw exception;
        }
    }
    try {
        return currentBatch.getResult();
    } catch (MongoException e) {
        retryState.markAsLastAttempt();
        throw e;
    }
}
Also used : MongoWriteConcernWithResponseException(com.mongodb.internal.connection.MongoWriteConcernWithResponseException) MongoException(com.mongodb.MongoException) BsonDocument(org.bson.BsonDocument) Assertions(com.mongodb.assertions.Assertions)

Example 2 with MongoWriteConcernWithResponseException

use of com.mongodb.internal.connection.MongoWriteConcernWithResponseException in project mongo-java-driver by mongodb.

the class MixedBulkWriteOperation method executeAsync.

public void executeAsync(final AsyncWriteBinding binding, final SingleResultCallback<BulkWriteResult> callback) {
    // see the comment in `execute(WriteBinding)` explaining the manual tracking of attempts
    RetryState retryState = new RetryState();
    BulkWriteTracker.attachNew(retryState, retryWrites);
    binding.retain();
    AsyncCallbackSupplier<BulkWriteResult> retryingBulkWrite = this.<BulkWriteResult>decorateWriteWithRetries(retryState, funcCallback -> {
        logRetryExecute(retryState);
        withAsyncSourceAndConnection(binding::getWriteConnectionSource, true, funcCallback, (source, connection, releasingCallback) -> {
            ConnectionDescription connectionDescription = connection.getDescription();
            int maxWireVersion = connectionDescription.getMaxWireVersion();
            // attach `maxWireVersion` ASAP because it is used to check whether we can retry
            retryState.attach(AttachmentKeys.maxWireVersion(), maxWireVersion, true);
            BulkWriteTracker bulkWriteTracker = retryState.attachment(AttachmentKeys.bulkWriteTracker()).orElseThrow(Assertions::fail);
            SessionContext sessionContext = binding.getSessionContext();
            WriteConcern writeConcern = getAppliedWriteConcern(sessionContext);
            if (!retryState.isFirstAttempt() && !isRetryableWrite(retryWrites, writeConcern, source.getServerDescription(), connectionDescription, sessionContext)) {
                Throwable prospectiveFailedResult = retryState.exception().orElse(null);
                if (retryState.breakAndCompleteIfRetryAnd(() -> !(prospectiveFailedResult instanceof MongoWriteConcernWithResponseException), releasingCallback)) {
                    return;
                }
                bulkWriteTracker.batch().ifPresent(bulkWriteBatch -> {
                    assertTrue(prospectiveFailedResult instanceof MongoWriteConcernWithResponseException);
                    bulkWriteBatch.addResult((BsonDocument) ((MongoWriteConcernWithResponseException) prospectiveFailedResult).getResponse());
                    BulkWriteTracker.attachNext(retryState, bulkWriteBatch);
                });
            }
            if (validateWriteRequestsAndCompleteIfInvalid(connectionDescription, bypassDocumentValidation, writeRequests, writeConcern, releasingCallback)) {
                return;
            }
            if (writeConcern.isAcknowledged() || serverIsAtLeastVersionThreeDotSix(connectionDescription)) {
                try {
                    if (!bulkWriteTracker.batch().isPresent()) {
                        BulkWriteTracker.attachNew(retryState, BulkWriteBatch.createBulkWriteBatch(namespace, source.getServerDescription(), connectionDescription, ordered, writeConcern, bypassDocumentValidation, retryWrites, writeRequests, sessionContext));
                    }
                } catch (Throwable t) {
                    releasingCallback.onResult(null, t);
                    return;
                }
                logRetryExecute(retryState);
                executeBulkWriteBatchAsync(retryState, binding, connection, maxWireVersion, releasingCallback);
            } else {
                retryState.markAsLastAttempt();
                executeLegacyBatchesAsync(binding, connection, releasingCallback);
            }
        });
    }).whenComplete(binding::release);
    retryingBulkWrite.get(exceptionTransformingCallback(errorHandlingCallback(callback, LOGGER)));
}
Also used : LoopState(com.mongodb.internal.async.function.LoopState) WriteRequest(com.mongodb.internal.bulk.WriteRequest) CommandOperationHelper.addRetryableWriteErrorLabel(com.mongodb.internal.operation.CommandOperationHelper.addRetryableWriteErrorLabel) MongoBulkWriteException(com.mongodb.MongoBulkWriteException) MongoWriteConcernWithResponseException(com.mongodb.internal.connection.MongoWriteConcernWithResponseException) ProtocolHelper(com.mongodb.internal.connection.ProtocolHelper) ConnectionDescription(com.mongodb.connection.ConnectionDescription) BsonArray(org.bson.BsonArray) OperationHelper.validateWriteRequests(com.mongodb.internal.operation.OperationHelper.validateWriteRequests) OperationHelper.withSourceAndConnection(com.mongodb.internal.operation.OperationHelper.withSourceAndConnection) MongoException(com.mongodb.MongoException) AsyncCallbackSupplier(com.mongodb.internal.async.function.AsyncCallbackSupplier) Set(java.util.Set) Collectors(java.util.stream.Collectors) AsyncCallbackRunnable(com.mongodb.internal.async.function.AsyncCallbackRunnable) ServerVersionHelper.serverIsAtLeastVersionThreeDotSix(com.mongodb.internal.operation.ServerVersionHelper.serverIsAtLeastVersionThreeDotSix) SingleResultCallback(com.mongodb.internal.async.SingleResultCallback) REPLACE(com.mongodb.internal.bulk.WriteRequest.Type.REPLACE) RetryState(com.mongodb.internal.async.function.RetryState) List(java.util.List) Assertions.notNull(com.mongodb.assertions.Assertions.notNull) Optional(java.util.Optional) RetryingSyncSupplier(com.mongodb.internal.async.function.RetryingSyncSupplier) InsertRequest(com.mongodb.internal.bulk.InsertRequest) RetryingAsyncCallbackSupplier(com.mongodb.internal.async.function.RetryingAsyncCallbackSupplier) CommandOperationHelper.logRetryExecute(com.mongodb.internal.operation.CommandOperationHelper.logRetryExecute) CommandOperationHelper.exceptionTransformingCallback(com.mongodb.internal.operation.CommandOperationHelper.exceptionTransformingCallback) ErrorHandlingResultCallback.errorHandlingCallback(com.mongodb.internal.async.ErrorHandlingResultCallback.errorHandlingCallback) BsonString(org.bson.BsonString) Supplier(java.util.function.Supplier) BsonDocument(org.bson.BsonDocument) LOGGER(com.mongodb.internal.operation.OperationHelper.LOGGER) Connection(com.mongodb.internal.connection.Connection) NoOpFieldNameValidator(com.mongodb.internal.validator.NoOpFieldNameValidator) WriteBinding(com.mongodb.internal.binding.WriteBinding) Assertions(com.mongodb.assertions.Assertions) WriteConcernResult(com.mongodb.WriteConcernResult) AsyncCallbackLoop(com.mongodb.internal.async.function.AsyncCallbackLoop) AsyncWriteBinding(com.mongodb.internal.binding.AsyncWriteBinding) DeleteRequest(com.mongodb.internal.bulk.DeleteRequest) SessionContext(com.mongodb.internal.session.SessionContext) FieldNameValidator(org.bson.FieldNameValidator) OperationHelper.validateWriteRequestsAndCompleteIfInvalid(com.mongodb.internal.operation.OperationHelper.validateWriteRequestsAndCompleteIfInvalid) INSERT(com.mongodb.internal.bulk.WriteRequest.Type.INSERT) MongoNamespace(com.mongodb.MongoNamespace) UpdateRequest(com.mongodb.internal.bulk.UpdateRequest) OperationHelper.isRetryableWrite(com.mongodb.internal.operation.OperationHelper.isRetryableWrite) CommandOperationHelper.transformWriteException(com.mongodb.internal.operation.CommandOperationHelper.transformWriteException) Assertions.isTrueArgument(com.mongodb.assertions.Assertions.isTrueArgument) Assertions.assertTrue(com.mongodb.assertions.Assertions.assertTrue) OperationHelper.withAsyncSourceAndConnection(com.mongodb.internal.operation.OperationHelper.withAsyncSourceAndConnection) BulkWriteResult(com.mongodb.bulk.BulkWriteResult) Nullable(com.mongodb.lang.Nullable) WriteConcern(com.mongodb.WriteConcern) UPDATE(com.mongodb.internal.bulk.WriteRequest.Type.UPDATE) AsyncConnection(com.mongodb.internal.connection.AsyncConnection) AttachmentKeys(com.mongodb.internal.operation.retry.AttachmentKeys) ConnectionDescription(com.mongodb.connection.ConnectionDescription) MongoWriteConcernWithResponseException(com.mongodb.internal.connection.MongoWriteConcernWithResponseException) BsonDocument(org.bson.BsonDocument) WriteConcern(com.mongodb.WriteConcern) SessionContext(com.mongodb.internal.session.SessionContext) BulkWriteResult(com.mongodb.bulk.BulkWriteResult) RetryState(com.mongodb.internal.async.function.RetryState)

Example 3 with MongoWriteConcernWithResponseException

use of com.mongodb.internal.connection.MongoWriteConcernWithResponseException in project mongo-java-driver by mongodb.

the class MixedBulkWriteOperation method executeBulkWriteBatchAsync.

private void executeBulkWriteBatchAsync(final RetryState retryState, final AsyncWriteBinding binding, final AsyncConnection connection, final int maxWireVersion, final SingleResultCallback<BulkWriteResult> callback) {
    LoopState loopState = new LoopState();
    AsyncCallbackRunnable loop = new AsyncCallbackLoop(loopState, iterationCallback -> {
        BulkWriteTracker currentBulkWriteTracker = retryState.attachment(AttachmentKeys.bulkWriteTracker()).orElseThrow(Assertions::fail);
        loopState.attach(AttachmentKeys.bulkWriteTracker(), currentBulkWriteTracker, true);
        BulkWriteBatch currentBatch = currentBulkWriteTracker.batch().orElseThrow(Assertions::fail);
        if (loopState.breakAndCompleteIf(() -> !currentBatch.shouldProcessBatch(), iterationCallback)) {
            return;
        }
        executeCommandAsync(binding, connection, currentBatch, (result, t) -> {
            if (t == null) {
                if (currentBatch.getRetryWrites() && !binding.getSessionContext().hasActiveTransaction()) {
                    MongoException writeConcernBasedError = ProtocolHelper.createSpecialException(result, connection.getDescription().getServerAddress(), "errMsg");
                    if (writeConcernBasedError != null) {
                        if (currentBulkWriteTracker.lastAttempt()) {
                            addRetryableWriteErrorLabel(writeConcernBasedError, maxWireVersion);
                            addErrorLabelsToWriteConcern(result.getDocument("writeConcernError"), writeConcernBasedError.getErrorLabels());
                        } else if (CommandOperationHelper.shouldAttemptToRetryWrite(retryState, writeConcernBasedError)) {
                            iterationCallback.onResult(null, new MongoWriteConcernWithResponseException(writeConcernBasedError, result));
                            return;
                        }
                    }
                }
                currentBatch.addResult(result);
                BulkWriteTracker.attachNext(retryState, currentBatch);
                iterationCallback.onResult(null, null);
            } else {
                if (t instanceof MongoException) {
                    MongoException exception = (MongoException) t;
                    if (!(retryState.isFirstAttempt() || (exception instanceof MongoWriteConcernWithResponseException))) {
                        addRetryableWriteErrorLabel(exception, maxWireVersion);
                    }
                }
                iterationCallback.onResult(null, t);
            }
        });
    });
    loop.run((voidResult, t) -> {
        if (t != null) {
            callback.onResult(null, t);
        } else {
            BulkWriteResult result;
            try {
                result = loopState.attachment(AttachmentKeys.bulkWriteTracker()).flatMap(BulkWriteTracker::batch).orElseThrow(Assertions::fail).getResult();
            } catch (Throwable loopResultT) {
                if (loopResultT instanceof MongoException) {
                    retryState.markAsLastAttempt();
                }
                callback.onResult(null, loopResultT);
                return;
            }
            callback.onResult(result, null);
        }
    });
}
Also used : LoopState(com.mongodb.internal.async.function.LoopState) AsyncCallbackRunnable(com.mongodb.internal.async.function.AsyncCallbackRunnable) MongoWriteConcernWithResponseException(com.mongodb.internal.connection.MongoWriteConcernWithResponseException) MongoException(com.mongodb.MongoException) AsyncCallbackLoop(com.mongodb.internal.async.function.AsyncCallbackLoop) Assertions(com.mongodb.assertions.Assertions) BulkWriteResult(com.mongodb.bulk.BulkWriteResult)

Example 4 with MongoWriteConcernWithResponseException

use of com.mongodb.internal.connection.MongoWriteConcernWithResponseException in project mongo-java-driver by mongodb.

the class MixedBulkWriteOperation method execute.

/**
 * Executes a bulk write operation.
 *
 * @param binding the WriteBinding        for the operation
 * @return the bulk write result.
 * @throws MongoBulkWriteException if a failure to complete the bulk write is detected based on the server response
 */
@Override
public BulkWriteResult execute(final WriteBinding binding) {
    /* We cannot use the tracking of attempts built in the `RetryState` class because conceptually we have to maintain multiple attempt
         * counters while executing a single bulk write operation:
         * - a counter that limits attempts to select server and checkout a connection before we created a batch;
         * - a counter per each batch that limits attempts to execute the specific batch.
         * Fortunately, these counters do not exist concurrently with each other. While maintaining the counters manually,
         * we must adhere to the contract of `RetryingSyncSupplier`. When the retry timeout is implemented, there will be no counters,
         * and the code related to the attempt tracking in `BulkWriteTracker` will be removed. */
    RetryState retryState = new RetryState();
    BulkWriteTracker.attachNew(retryState, retryWrites);
    Supplier<BulkWriteResult> retryingBulkWrite = decorateWriteWithRetries(retryState, () -> {
        logRetryExecute(retryState);
        return withSourceAndConnection(binding::getWriteConnectionSource, true, (source, connection) -> {
            ConnectionDescription connectionDescription = connection.getDescription();
            int maxWireVersion = connectionDescription.getMaxWireVersion();
            // attach `maxWireVersion` ASAP because it is used to check whether we can retry
            retryState.attach(AttachmentKeys.maxWireVersion(), maxWireVersion, true);
            BulkWriteTracker bulkWriteTracker = retryState.attachment(AttachmentKeys.bulkWriteTracker()).orElseThrow(Assertions::fail);
            SessionContext sessionContext = binding.getSessionContext();
            WriteConcern writeConcern = getAppliedWriteConcern(sessionContext);
            if (!retryState.isFirstAttempt() && !isRetryableWrite(retryWrites, writeConcern, source.getServerDescription(), connectionDescription, sessionContext)) {
                RuntimeException prospectiveFailedResult = (RuntimeException) retryState.exception().orElse(null);
                retryState.breakAndThrowIfRetryAnd(() -> !(prospectiveFailedResult instanceof MongoWriteConcernWithResponseException));
                bulkWriteTracker.batch().ifPresent(bulkWriteBatch -> {
                    assertTrue(prospectiveFailedResult instanceof MongoWriteConcernWithResponseException);
                    bulkWriteBatch.addResult((BsonDocument) ((MongoWriteConcernWithResponseException) prospectiveFailedResult).getResponse());
                    BulkWriteTracker.attachNext(retryState, bulkWriteBatch);
                });
            }
            validateWriteRequests(connectionDescription, bypassDocumentValidation, writeRequests, writeConcern);
            if (writeConcern.isAcknowledged() || serverIsAtLeastVersionThreeDotSix(connectionDescription)) {
                if (!bulkWriteTracker.batch().isPresent()) {
                    BulkWriteTracker.attachNew(retryState, BulkWriteBatch.createBulkWriteBatch(namespace, source.getServerDescription(), connectionDescription, ordered, writeConcern, bypassDocumentValidation, retryWrites, writeRequests, sessionContext));
                }
                logRetryExecute(retryState);
                return executeBulkWriteBatch(retryState, binding, connection, maxWireVersion);
            } else {
                retryState.markAsLastAttempt();
                return executeLegacyBatches(binding, connection);
            }
        });
    });
    try {
        return retryingBulkWrite.get();
    } catch (MongoException e) {
        throw transformWriteException(e);
    }
}
Also used : MongoException(com.mongodb.MongoException) Assertions(com.mongodb.assertions.Assertions) BulkWriteResult(com.mongodb.bulk.BulkWriteResult) ConnectionDescription(com.mongodb.connection.ConnectionDescription) MongoWriteConcernWithResponseException(com.mongodb.internal.connection.MongoWriteConcernWithResponseException) WriteConcern(com.mongodb.WriteConcern) SessionContext(com.mongodb.internal.session.SessionContext) RetryState(com.mongodb.internal.async.function.RetryState)

Aggregations

MongoException (com.mongodb.MongoException)4 Assertions (com.mongodb.assertions.Assertions)4 MongoWriteConcernWithResponseException (com.mongodb.internal.connection.MongoWriteConcernWithResponseException)4 BulkWriteResult (com.mongodb.bulk.BulkWriteResult)3 WriteConcern (com.mongodb.WriteConcern)2 ConnectionDescription (com.mongodb.connection.ConnectionDescription)2 AsyncCallbackLoop (com.mongodb.internal.async.function.AsyncCallbackLoop)2 AsyncCallbackRunnable (com.mongodb.internal.async.function.AsyncCallbackRunnable)2 LoopState (com.mongodb.internal.async.function.LoopState)2 RetryState (com.mongodb.internal.async.function.RetryState)2 BsonDocument (org.bson.BsonDocument)2 MongoBulkWriteException (com.mongodb.MongoBulkWriteException)1 MongoNamespace (com.mongodb.MongoNamespace)1 WriteConcernResult (com.mongodb.WriteConcernResult)1 Assertions.assertTrue (com.mongodb.assertions.Assertions.assertTrue)1 Assertions.isTrueArgument (com.mongodb.assertions.Assertions.isTrueArgument)1 Assertions.notNull (com.mongodb.assertions.Assertions.notNull)1 ErrorHandlingResultCallback.errorHandlingCallback (com.mongodb.internal.async.ErrorHandlingResultCallback.errorHandlingCallback)1 SingleResultCallback (com.mongodb.internal.async.SingleResultCallback)1 AsyncCallbackSupplier (com.mongodb.internal.async.function.AsyncCallbackSupplier)1