package com.netflix.astyanax.contrib.dualwrites;
import java.util.Collection;
import com.google.common.util.concurrent.ListenableFuture;
import com.netflix.astyanax.Execution;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
/**
* Impl of {@link DualWritesStrategy} that writes SEQUENTIALLY to the 2 keyspaces.
* first the primary and then the secondary.
*
* If the 1st keyspace write fails, then the failure is propagated immediately to the caller.
* If the 1st one succeeds then the 2nd keyspace is tried as best effort. If the write to the 2nd keyspace fails,
* then that failed write is given to the provided {@link FailedWritesLogger} which can then decide what to do with it.
*
* @author poberai
*
*/
public class BestEffortSecondaryWriteStrategy implements DualWritesStrategy {
private final FailedWritesLogger failedWritesLogger;
public BestEffortSecondaryWriteStrategy(FailedWritesLogger logger) {
this.failedWritesLogger = logger;
}
@Override
public <R> Execution<R> wrapExecutions(final Execution<R> primary, final Execution<R> secondary, final Collection<WriteMetadata> writeMetadata) {
return new Execution<R>() {
@Override
public OperationResult<R> execute() throws ConnectionException {
OperationResult<R> result = primary.execute();
try {
secondary.execute();
} catch (ConnectionException e) {
if (failedWritesLogger != null) {
for (WriteMetadata writeMD : writeMetadata) {
failedWritesLogger.logFailedWrite(writeMD);
}
}
}
return result;
}
@Override
public ListenableFuture<OperationResult<R>> executeAsync() throws ConnectionException {
throw new RuntimeException("Cannot chain async primary and secondary executions");
}
};
}
@Override
public FailedWritesLogger getFailedWritesLogger() {
return failedWritesLogger;
}
}