All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scalar.database.storage.cassandra.MutateStatementHandler Maven / Gradle / Ivy

Go to download

A universal transaction manager that achieves database-agnostic transactions and distributed transactions that span multiple databases

There is a newer version: 3.14.0-alpha.1
Show newest version
package com.scalar.database.storage.cassandra;

import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.WriteType;
import com.datastax.driver.core.exceptions.WriteTimeoutException;
import com.datastax.driver.core.querybuilder.BuiltStatement;
import com.scalar.database.api.Mutation;
import com.scalar.database.api.Operation;
import com.scalar.database.exception.storage.ExecutionException;
import com.scalar.database.exception.storage.NoMutationException;
import com.scalar.database.exception.storage.ReadRepairableExecutionException;
import com.scalar.database.exception.storage.RetriableExecutionException;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ThreadSafe
public abstract class MutateStatementHandler extends StatementHandler {
  private static final Logger LOGGER = LoggerFactory.getLogger(MutateStatementHandler.class);

  public MutateStatementHandler(Session session) {
    super(session);
  }

  /**
   * Executes the specified 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);
    }
  }

  @Override
  protected void overwriteConsistency(BoundStatement bound, Operation operation) {
    ((Mutation) operation)
        .getCondition()
        .ifPresent(
            c -> {
              bound.setConsistencyLevel(ConsistencyLevel.QUORUM); // for learn phase
              bound.setSerialConsistencyLevel(ConsistencyLevel.SERIAL); // for paxos phase
            });
  }

  protected void setCondition(BuiltStatement statement, Mutation mutation) {
    mutation
        .getCondition()
        .ifPresent(
            c -> {
              c.accept(new ConditionSetter(statement));
            });
  }

  protected void bindCondition(ValueBinder binder, Mutation mutation) {
    mutation
        .getCondition()
        .ifPresent(
            c -> {
              c.getExpressions().forEach(e -> e.getValue().accept(binder));
            });
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy