use of com.datastax.driver.core.ResultSetFuture in project flink by apache.
the class CassandraTupleWriteAheadSinkTest method testAckLoopExitOnException.
@Test(timeout = 20000)
public void testAckLoopExitOnException() throws Exception {
final AtomicReference<Runnable> runnableFuture = new AtomicReference<>();
final ClusterBuilder clusterBuilder = new ClusterBuilder() {
private static final long serialVersionUID = 4624400760492936756L;
@Override
protected Cluster buildCluster(Cluster.Builder builder) {
try {
BoundStatement boundStatement = mock(BoundStatement.class);
when(boundStatement.setDefaultTimestamp(any(long.class))).thenReturn(boundStatement);
PreparedStatement preparedStatement = mock(PreparedStatement.class);
when(preparedStatement.bind(Matchers.anyVararg())).thenReturn(boundStatement);
ResultSetFuture future = mock(ResultSetFuture.class);
when(future.get()).thenThrow(new RuntimeException("Expected exception."));
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
synchronized (runnableFuture) {
runnableFuture.set((((Runnable) invocationOnMock.getArguments()[0])));
runnableFuture.notifyAll();
}
return null;
}
}).when(future).addListener(any(Runnable.class), any(Executor.class));
Session session = mock(Session.class);
when(session.prepare(anyString())).thenReturn(preparedStatement);
when(session.executeAsync(any(BoundStatement.class))).thenReturn(future);
Cluster cluster = mock(Cluster.class);
when(cluster.connect()).thenReturn(session);
return cluster;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
// Our asynchronous executor thread
new Thread(new Runnable() {
@Override
public void run() {
synchronized (runnableFuture) {
while (runnableFuture.get() == null) {
try {
runnableFuture.wait();
} catch (InterruptedException e) {
// ignore interrupts
}
}
}
runnableFuture.get().run();
}
}).start();
CheckpointCommitter cc = mock(CheckpointCommitter.class);
final CassandraTupleWriteAheadSink<Tuple0> sink = new CassandraTupleWriteAheadSink<>("abc", TupleTypeInfo.of(Tuple0.class).createSerializer(new ExecutionConfig()), clusterBuilder, cc);
OneInputStreamOperatorTestHarness<Tuple0, Tuple0> harness = new OneInputStreamOperatorTestHarness<>(sink);
harness.getEnvironment().getTaskConfiguration().setBoolean("checkpointing", true);
harness.setup();
sink.open();
// we should leave the loop and return false since we've seen an exception
assertFalse(sink.sendValues(Collections.singleton(new Tuple0()), 1L, 0L));
sink.close();
}
use of com.datastax.driver.core.ResultSetFuture in project flink by apache.
the class CassandraRowWriteAheadSink method sendValues.
@Override
protected boolean sendValues(Iterable<Row> values, long checkpointId, long timestamp) throws Exception {
final AtomicInteger updatesCount = new AtomicInteger(0);
final AtomicInteger updatesConfirmed = new AtomicInteger(0);
final AtomicReference<Throwable> exception = new AtomicReference<>();
FutureCallback<ResultSet> callback = new FutureCallback<ResultSet>() {
@Override
public void onSuccess(ResultSet resultSet) {
updatesConfirmed.incrementAndGet();
if (updatesCount.get() > 0) {
// only set if all updates have been sent
if (updatesCount.get() == updatesConfirmed.get()) {
synchronized (updatesConfirmed) {
updatesConfirmed.notifyAll();
}
}
}
}
@Override
public void onFailure(Throwable throwable) {
if (exception.compareAndSet(null, throwable)) {
LOG.error("Error while sending value.", throwable);
synchronized (updatesConfirmed) {
updatesConfirmed.notifyAll();
}
}
}
};
// set values for prepared statement
int updatesSent = 0;
for (Row value : values) {
for (int x = 0; x < arity; x++) {
fields[x] = value.getField(x);
}
// insert values and send to cassandra
BoundStatement s = preparedStatement.bind(fields);
s.setDefaultTimestamp(timestamp);
ResultSetFuture result = session.executeAsync(s);
updatesSent++;
if (result != null) {
// add callback to detect errors
Futures.addCallback(result, callback);
}
}
updatesCount.set(updatesSent);
synchronized (updatesConfirmed) {
while (exception.get() == null && updatesSent != updatesConfirmed.get()) {
updatesConfirmed.wait();
}
}
if (exception.get() != null) {
LOG.warn("Sending a value failed.", exception.get());
return false;
} else {
return true;
}
}
use of com.datastax.driver.core.ResultSetFuture in project flink by apache.
the class CassandraTupleWriteAheadSink method sendValues.
@Override
protected boolean sendValues(Iterable<IN> values, long checkpointId, long timestamp) throws Exception {
final AtomicInteger updatesCount = new AtomicInteger(0);
final AtomicInteger updatesConfirmed = new AtomicInteger(0);
final AtomicReference<Throwable> exception = new AtomicReference<>();
FutureCallback<ResultSet> callback = new FutureCallback<ResultSet>() {
@Override
public void onSuccess(ResultSet resultSet) {
updatesConfirmed.incrementAndGet();
if (updatesCount.get() > 0) {
// only set if all updates have been sent
if (updatesCount.get() == updatesConfirmed.get()) {
synchronized (updatesConfirmed) {
updatesConfirmed.notifyAll();
}
}
}
}
@Override
public void onFailure(Throwable throwable) {
if (exception.compareAndSet(null, throwable)) {
LOG.error("Error while sending value.", throwable);
synchronized (updatesConfirmed) {
updatesConfirmed.notifyAll();
}
}
}
};
// set values for prepared statement
int updatesSent = 0;
for (IN value : values) {
for (int x = 0; x < value.getArity(); x++) {
fields[x] = value.getField(x);
}
// insert values and send to cassandra
BoundStatement s = preparedStatement.bind(fields);
s.setDefaultTimestamp(timestamp);
ResultSetFuture result = session.executeAsync(s);
updatesSent++;
if (result != null) {
// add callback to detect errors
Futures.addCallback(result, callback);
}
}
updatesCount.set(updatesSent);
synchronized (updatesConfirmed) {
while (exception.get() == null && updatesSent != updatesConfirmed.get()) {
updatesConfirmed.wait();
}
}
if (exception.get() != null) {
LOG.warn("Sending a value failed.", exception.get());
return false;
} else {
return true;
}
}
use of com.datastax.driver.core.ResultSetFuture in project ignite by apache.
the class CassandraSessionImpl method execute.
/**
* {@inheritDoc}
*/
@Override
public <R, V> R execute(BatchExecutionAssistant<R, V> assistant, Iterable<? extends V> data) {
if (data == null || !data.iterator().hasNext())
return assistant.processedData();
int attempt = 0;
String errorMsg = "Failed to execute Cassandra " + assistant.operationName() + " operation";
Throwable error = new IgniteException(errorMsg);
RandomSleeper sleeper = newSleeper();
int dataSize = 0;
incrementSessionRefs();
try {
while (attempt < CQL_EXECUTION_ATTEMPTS_COUNT) {
if (attempt != 0) {
log.warning("Trying " + (attempt + 1) + " attempt to execute Cassandra batch " + assistant.operationName() + " operation to process rest " + (dataSize - assistant.processedCount()) + " of " + dataSize + " elements");
}
// clean errors info before next communication with Cassandra
Throwable unknownEx = null;
Throwable tblAbsenceEx = null;
Throwable hostsAvailEx = null;
Throwable prepStatEx = null;
List<Cache.Entry<Integer, ResultSetFuture>> futResults = new LinkedList<>();
WrappedPreparedStatement preparedSt = prepareStatement(assistant.getTable(), assistant.getStatement(), assistant.getPersistenceSettings(), assistant.tableExistenceRequired());
if (preparedSt == null)
return null;
WrappedSession ses = null;
int seqNum = 0;
for (V obj : data) {
if (!assistant.alreadyProcessed(seqNum)) {
try {
ses = session();
Statement statement = tuneStatementExecutionOptions(assistant.bindStatement(preparedSt, obj));
ResultSetFuture fut = ses.executeAsync(statement);
futResults.add(new CacheEntryImpl<>(seqNum, fut));
} catch (Throwable e) {
if (CassandraHelper.isTableAbsenceError(e)) {
// If there are table absence error and it is not required for the operation we can return.
if (!assistant.tableExistenceRequired())
return assistant.processedData();
tblAbsenceEx = e;
handleTableAbsenceError(assistant.getTable(), assistant.getPersistenceSettings());
} else if (CassandraHelper.isHostsAvailabilityError(e)) {
hostsAvailEx = e;
// Handle host availability only once.
if (hostsAvailEx == null)
handleHostsAvailabilityError(ses == null ? 0 : ses.generation, e, attempt, errorMsg);
} else if (CassandraHelper.isPreparedStatementClusterError(e)) {
prepStatEx = e;
handlePreparedStatementClusterError(preparedSt.generation, e);
preparedSt = prepareStatement(assistant.getTable(), assistant.getStatement(), assistant.getPersistenceSettings(), assistant.tableExistenceRequired());
if (preparedSt == null)
return null;
} else
unknownEx = e;
}
}
seqNum++;
}
dataSize = seqNum;
// For an error which we don't know how to handle, we will not try next attempts and terminate.
if (unknownEx != null)
throw new IgniteException(errorMsg, unknownEx);
// Remembering any of last errors.
if (tblAbsenceEx != null)
error = tblAbsenceEx;
else if (hostsAvailEx != null)
error = hostsAvailEx;
else if (prepStatEx != null)
error = prepStatEx;
// Clean errors info before next communication with Cassandra.
unknownEx = null;
tblAbsenceEx = null;
hostsAvailEx = null;
prepStatEx = null;
for (Cache.Entry<Integer, ResultSetFuture> futureResult : futResults) {
try {
ResultSet resSet = futureResult.getValue().getUninterruptibly();
Row row = resSet != null && resSet.iterator().hasNext() ? resSet.iterator().next() : null;
assistant.process(row, futureResult.getKey());
} catch (Throwable e) {
if (CassandraHelper.isTableAbsenceError(e))
tblAbsenceEx = e;
else if (CassandraHelper.isHostsAvailabilityError(e))
hostsAvailEx = e;
else if (CassandraHelper.isPreparedStatementClusterError(e))
prepStatEx = e;
else
unknownEx = e;
}
}
// For an error which we don't know how to handle, we will not try next attempts and terminate.
if (unknownEx != null)
throw new IgniteException(errorMsg, unknownEx);
// If there are no errors occurred it means that operation successfully completed and we can return.
if (tblAbsenceEx == null && hostsAvailEx == null && prepStatEx == null && assistant.processedCount() == dataSize)
return assistant.processedData();
if (tblAbsenceEx != null) {
// If there are table absence error and it is not required for the operation we can return.
if (!assistant.tableExistenceRequired())
return assistant.processedData();
error = tblAbsenceEx;
handleTableAbsenceError(assistant.getTable(), assistant.getPersistenceSettings());
}
if (hostsAvailEx != null) {
error = hostsAvailEx;
handleHostsAvailabilityError(ses.generation, hostsAvailEx, attempt, errorMsg);
}
if (prepStatEx != null) {
error = prepStatEx;
handlePreparedStatementClusterError(preparedSt.generation, prepStatEx);
}
if (!CassandraHelper.isTableAbsenceError(error))
sleeper.sleep();
attempt++;
}
} catch (Throwable e) {
error = e;
} finally {
decrementSessionRefs();
}
errorMsg = "Failed to process " + (dataSize - assistant.processedCount()) + " of " + dataSize + " elements, during " + assistant.operationName() + " operation with Cassandra";
LT.warn(log, error, errorMsg, false, false);
throw new IgniteException(errorMsg, error);
}
use of com.datastax.driver.core.ResultSetFuture in project ignite by apache.
the class CassandraSessionImpl method execute.
/**
* {@inheritDoc}
*/
@Override
public void execute(BatchLoaderAssistant assistant) {
int attempt = 0;
String errorMsg = "Failed to execute Cassandra " + assistant.operationName() + " operation";
Throwable error = new IgniteException(errorMsg);
RandomSleeper sleeper = newSleeper();
incrementSessionRefs();
try {
while (attempt < CQL_EXECUTION_ATTEMPTS_COUNT) {
if (attempt != 0)
log.warning("Trying " + (attempt + 1) + " attempt to load Ignite cache");
Statement statement = tuneStatementExecutionOptions(assistant.getStatement());
WrappedSession ses = null;
try {
ses = session();
ResultSetFuture fut = ses.executeAsync(statement);
ResultSet resSet = fut.getUninterruptibly();
if (resSet == null || !resSet.iterator().hasNext())
return;
for (Row row : resSet) assistant.process(row);
return;
} catch (Throwable e) {
error = e;
if (CassandraHelper.isTableAbsenceError(e))
return;
else if (CassandraHelper.isHostsAvailabilityError(e))
handleHostsAvailabilityError(ses == null ? 0 : ses.generation, e, attempt, errorMsg);
else
// For an error which we don't know how to handle, we will not try next attempts and terminate.
throw new IgniteException(errorMsg, e);
}
sleeper.sleep();
attempt++;
}
} catch (Throwable e) {
error = e;
} finally {
decrementSessionRefs();
}
log.error(errorMsg, error);
throw new IgniteException(errorMsg, error);
}
Aggregations