Search in sources :

Example 1 with RetriableExecutionException

use of com.scalar.db.exception.storage.RetriableExecutionException in project scalardb by scalar-labs.

the class PutStatementHandler method handle.

@Nonnull
@Override
public List<Map<String, AttributeValue>> handle(Operation operation) throws ExecutionException {
    checkArgument(operation, Put.class);
    Put put = (Put) operation;
    TableMetadata tableMetadata = metadataManager.getTableMetadata(operation);
    try {
        execute(put, tableMetadata);
    } catch (ConditionalCheckFailedException e) {
        throw new NoMutationException("no mutation was applied.", e);
    } catch (TransactionConflictException e) {
        throw new RetriableExecutionException(e.getMessage(), e);
    } catch (DynamoDbException e) {
        throw new ExecutionException(e.getMessage(), e);
    }
    return Collections.emptyList();
}
Also used : TableMetadata(com.scalar.db.api.TableMetadata) DynamoDbException(software.amazon.awssdk.services.dynamodb.model.DynamoDbException) TransactionConflictException(software.amazon.awssdk.services.dynamodb.model.TransactionConflictException) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) ExecutionException(com.scalar.db.exception.storage.ExecutionException) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) ConditionalCheckFailedException(software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException) NoMutationException(com.scalar.db.exception.storage.NoMutationException) Put(com.scalar.db.api.Put) Nonnull(javax.annotation.Nonnull)

Example 2 with RetriableExecutionException

use of com.scalar.db.exception.storage.RetriableExecutionException in project scalardb by scalar-labs.

the class BatchHandler method handle.

/**
 * Execute the specified list of {@link Mutation}s in batch. All the {@link Mutation}s in the list
 * must be for the same partition.
 *
 * @param mutations a list of {@code Mutation}s to execute
 * @throws NoMutationException if at least one of conditional {@code Mutation}s failed because it
 *     didn't meet the condition
 */
public void handle(List<? extends Mutation> mutations) throws ExecutionException {
    if (mutations.size() > 25) {
        throw new IllegalArgumentException("DynamoDB cannot batch more than 25 mutations at once.");
    }
    TableMetadata tableMetadata = metadataManager.getTableMetadata(mutations.get(0));
    TransactWriteItemsRequest.Builder builder = TransactWriteItemsRequest.builder();
    List<TransactWriteItem> transactItems = new ArrayList<>();
    mutations.forEach(m -> transactItems.add(makeWriteItem(m, tableMetadata)));
    builder.transactItems(transactItems);
    try {
        client.transactWriteItems(builder.build());
    } catch (TransactionCanceledException e) {
        boolean allReasonsAreTransactionConflicts = true;
        for (CancellationReason reason : e.cancellationReasons()) {
            if (reason.code().equals("ConditionalCheckFailed")) {
                throw new NoMutationException("no mutation was applied.", e);
            }
            if (!reason.code().equals("TransactionConflict") && !reason.code().equals("None")) {
                allReasonsAreTransactionConflicts = false;
            }
        }
        if (allReasonsAreTransactionConflicts) {
            // RetriableExecutionException
            throw new RetriableExecutionException(e.getMessage(), e);
        }
        throw new ExecutionException(e.getMessage(), e);
    } catch (DynamoDbException e) {
        throw new ExecutionException(e.getMessage(), e);
    }
}
Also used : TableMetadata(com.scalar.db.api.TableMetadata) CancellationReason(software.amazon.awssdk.services.dynamodb.model.CancellationReason) TransactWriteItemsRequest(software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest) ArrayList(java.util.ArrayList) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) TransactionCanceledException(software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException) DynamoDbException(software.amazon.awssdk.services.dynamodb.model.DynamoDbException) TransactWriteItem(software.amazon.awssdk.services.dynamodb.model.TransactWriteItem) ExecutionException(com.scalar.db.exception.storage.ExecutionException) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) NoMutationException(com.scalar.db.exception.storage.NoMutationException)

Example 3 with RetriableExecutionException

use of com.scalar.db.exception.storage.RetriableExecutionException in project scalardb by scalar-labs.

the class BatchHandler method throwException.

private void throwException(CosmosException exception) throws ExecutionException {
    LOGGER.error(exception.getMessage(), exception);
    int statusCode = exception.getSubStatusCode();
    if (statusCode == CosmosErrorCode.PRECONDITION_FAILED.get()) {
        throw new NoMutationException("no mutation was applied.");
    } else if (statusCode == CosmosErrorCode.RETRY_WITH.get()) {
        throw new RetriableExecutionException(exception.getMessage(), exception);
    }
    throw new ExecutionException(exception.getMessage(), exception);
}
Also used : RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) ExecutionException(com.scalar.db.exception.storage.ExecutionException) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) NoMutationException(com.scalar.db.exception.storage.NoMutationException)

Example 4 with RetriableExecutionException

use of com.scalar.db.exception.storage.RetriableExecutionException in project scalardb by scalar-labs.

the class MutateStatementHandler method handle.

/**
 * Executes the specified {@link Mutation} {@link Operation}
 *
 * @param operation {@link Mutation} operation
 * @return a {@code ResultSet}
 * @throws RetriableExecutionException if the execution failed, but it can be retriable
 * @throws ReadRepairableExecutionException if the execution partially failed, which can be
 *     repaired by a following read
 */
@Override
@Nonnull
public ResultSet handle(Operation operation) throws ExecutionException {
    try {
        ResultSet results = handleInternal(operation);
        Mutation mutation = (Mutation) operation;
        if (mutation.getCondition().isPresent() && !results.one().getBool(0)) {
            throw new NoMutationException("no mutation was applied.");
        }
        return results;
    } catch (WriteTimeoutException e) {
        LOGGER.warn("write timeout happened during mutate operation.", e);
        if (e.getWriteType() == WriteType.CAS) {
            // retry needs to be done if applications need to do the operation exactly
            throw new RetriableExecutionException("paxos phase in CAS operation failed.", e);
        } else if (e.getWriteType() == WriteType.SIMPLE) {
            Mutation mutation = (Mutation) operation;
            if (mutation.getCondition().isPresent()) {
                // learn phase needs to be repaired (by re-reading)
                throw new ReadRepairableExecutionException("learn phase in CAS operation failed.", e);
            } else {
                // retry needs to be done if applications need to do the operation exactly
                throw new RetriableExecutionException("simple write operation failed.", e);
            }
        } else {
            throw new ExecutionException("something wrong because it is neither CAS nor SIMPLE", e);
        }
    } catch (RuntimeException e) {
        LOGGER.warn(e.getMessage(), e);
        throw new RetriableExecutionException(e.getMessage(), e);
    }
}
Also used : WriteTimeoutException(com.datastax.driver.core.exceptions.WriteTimeoutException) ResultSet(com.datastax.driver.core.ResultSet) Mutation(com.scalar.db.api.Mutation) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) ExecutionException(com.scalar.db.exception.storage.ExecutionException) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) NoMutationException(com.scalar.db.exception.storage.NoMutationException) Nonnull(javax.annotation.Nonnull)

Example 5 with RetriableExecutionException

use of com.scalar.db.exception.storage.RetriableExecutionException in project scalardb by scalar-labs.

the class JdbcDatabase method mutate.

@Override
public void mutate(List<? extends Mutation> mutations) throws ExecutionException {
    if (mutations.size() == 1) {
        Mutation mutation = mutations.get(0);
        if (mutation instanceof Put) {
            put((Put) mutation);
        } else if (mutation instanceof Delete) {
            delete((Delete) mutation);
        }
        return;
    }
    mutations = copyAndSetTargetToIfNot(mutations);
    Connection connection = null;
    try {
        connection = dataSource.getConnection();
        connection.setAutoCommit(false);
    } catch (SQLException e) {
        close(connection);
        throw new ExecutionException("mutate operation failed", e);
    }
    try {
        if (!jdbcService.mutate(mutations, connection)) {
            try {
                connection.rollback();
            } catch (SQLException e) {
                throw new ExecutionException("failed to rollback", e);
            }
            throw new NoMutationException("no mutation was applied");
        } else {
            connection.commit();
        }
    } catch (SQLException e) {
        try {
            connection.rollback();
        } catch (SQLException sqlException) {
            throw new ExecutionException("failed to rollback", sqlException);
        }
        if (JdbcUtils.isConflictError(e, rdbEngine)) {
            // conflicts can happen. Throw RetriableExecutionException in that case.
            throw new RetriableExecutionException("conflict happened in a mutate operation", e);
        }
        throw new ExecutionException("mutate operation failed", e);
    } finally {
        close(connection);
    }
}
Also used : Delete(com.scalar.db.api.Delete) SQLException(java.sql.SQLException) Connection(java.sql.Connection) Mutation(com.scalar.db.api.Mutation) ExecutionException(com.scalar.db.exception.storage.ExecutionException) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) RetriableExecutionException(com.scalar.db.exception.storage.RetriableExecutionException) NoMutationException(com.scalar.db.exception.storage.NoMutationException) Put(com.scalar.db.api.Put)

Aggregations

ExecutionException (com.scalar.db.exception.storage.ExecutionException)7 NoMutationException (com.scalar.db.exception.storage.NoMutationException)7 RetriableExecutionException (com.scalar.db.exception.storage.RetriableExecutionException)7 TableMetadata (com.scalar.db.api.TableMetadata)3 Nonnull (javax.annotation.Nonnull)3 DynamoDbException (software.amazon.awssdk.services.dynamodb.model.DynamoDbException)3 Delete (com.scalar.db.api.Delete)2 Mutation (com.scalar.db.api.Mutation)2 Put (com.scalar.db.api.Put)2 ConditionalCheckFailedException (software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException)2 TransactionConflictException (software.amazon.awssdk.services.dynamodb.model.TransactionConflictException)2 ResultSet (com.datastax.driver.core.ResultSet)1 WriteTimeoutException (com.datastax.driver.core.exceptions.WriteTimeoutException)1 Connection (java.sql.Connection)1 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 CancellationReason (software.amazon.awssdk.services.dynamodb.model.CancellationReason)1 TransactWriteItem (software.amazon.awssdk.services.dynamodb.model.TransactWriteItem)1 TransactWriteItemsRequest (software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest)1 TransactionCanceledException (software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException)1