use of com.datastax.oss.protocol.internal.response.Error in project java-driver by datastax.
the class ContinuousCqlRequestHandlerRetryTest method should_always_try_next_node_if_bootstrapping.
@Test
@UseDataProvider("allIdempotenceConfigs")
public void should_always_try_next_node_if_bootstrapping(boolean defaultIdempotence, Statement<?> statement, DseProtocolVersion version) {
try (RequestHandlerTestHarness harness = continuousHarnessBuilder().withProtocolVersion(version).withDefaultIdempotence(defaultIdempotence).withResponse(node1, defaultFrameOf(new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message"))).withResponse(node2, defaultFrameOf(DseTestFixtures.singleDseRow())).build()) {
ContinuousCqlRequestHandler handler = new ContinuousCqlRequestHandler(statement, harness.getSession(), harness.getContext(), "test");
CompletionStage<ContinuousAsyncResultSet> resultSetFuture = handler.handle();
assertThat(handler.getState()).isEqualTo(-1);
assertThatStage(resultSetFuture).isSuccess(resultSet -> {
Iterator<Row> rows = resultSet.currentPage().iterator();
assertThat(rows.hasNext()).isTrue();
assertThat(rows.next().getString("message")).isEqualTo("hello, world");
ExecutionInfo executionInfo = resultSet.getExecutionInfo();
assertThat(executionInfo.getCoordinator()).isEqualTo(node2);
assertThat(executionInfo.getErrors()).hasSize(1);
assertThat(executionInfo.getErrors().get(0).getKey()).isEqualTo(node1);
assertThat(executionInfo.getErrors().get(0).getValue()).isInstanceOf(BootstrappingException.class);
assertThat(executionInfo.getIncomingPayload()).isEmpty();
assertThat(executionInfo.getPagingState()).isNull();
assertThat(executionInfo.getSpeculativeExecutionCount()).isEqualTo(0);
assertThat(executionInfo.getSuccessfulExecutionIndex()).isEqualTo(0);
assertThat(executionInfo.getWarnings()).isEmpty();
Mockito.verifyNoMoreInteractions(harness.getContext().getRetryPolicy(anyString()));
});
}
}
use of com.datastax.oss.protocol.internal.response.Error in project java-driver by datastax.
the class FrameDecoder method decode.
@Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
int startIndex = in.readerIndex();
if (isFirstResponse) {
isFirstResponse = false;
// Must read at least the protocol v1/v2 header (see below)
if (in.readableBytes() < 8) {
return null;
}
// Special case for obsolete protocol versions (< v3): the length field is at a different
// position, so we can't delegate to super.decode() which would read the wrong length.
int protocolVersion = (int) in.getByte(startIndex) & 0b0111_1111;
if (protocolVersion < 3) {
int streamId = in.getByte(startIndex + 2);
int length = in.getInt(startIndex + 4);
// incoming data and spoof a server-side protocol error.
if (in.readableBytes() < 8 + length) {
// keep reading until we can discard the whole message at once
return null;
} else {
in.readerIndex(startIndex + 8 + length);
}
return Frame.forResponse(protocolVersion, streamId, null, Frame.NO_PAYLOAD, Collections.emptyList(), new Error(ProtocolConstants.ErrorCode.PROTOCOL_ERROR, "Invalid or unsupported protocol version"));
}
}
try {
ByteBuf buffer = (ByteBuf) super.decode(ctx, in);
return (buffer == null) ? // did not receive whole frame yet, keep reading
null : frameCodec.decode(buffer);
} catch (Exception e) {
// If decoding failed, try to read at least the stream id, so that the error can be
// propagated to the client request matching that id (otherwise we have to fail all
// pending requests on this channel)
int streamId;
try {
streamId = in.getShort(startIndex + 2);
} catch (Exception e1) {
// Should never happen, super.decode does not return a non-null buffer until the length
// field has been read, and the stream id comes before
Loggers.warnWithException(LOG, "Unexpected error while reading stream id", e1);
streamId = -1;
}
if (e instanceof TooLongFrameException) {
// Translate the Netty error to our own type
e = new FrameTooLongException(ctx.channel().remoteAddress(), e.getMessage());
}
throw new FrameDecodingException(streamId, e);
}
}
use of com.datastax.oss.protocol.internal.response.Error in project java-driver by datastax.
the class CqlPrepareHandlerTest method should_fail_if_retry_policy_ignores_error.
@Test
public void should_fail_if_retry_policy_ignores_error() {
RequestHandlerTestHarness.Builder harnessBuilder = RequestHandlerTestHarness.builder().withResponse(node1, defaultFrameOf(new Error(ProtocolConstants.ErrorCode.OVERLOADED, "mock message")));
PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2);
PoolBehavior node3Behavior = harnessBuilder.customBehavior(node3);
try (RequestHandlerTestHarness harness = harnessBuilder.build()) {
// Make node1's error unrecoverable, will rethrow
RetryPolicy mockRetryPolicy = harness.getContext().getRetryPolicy(DriverExecutionProfile.DEFAULT_NAME);
when(mockRetryPolicy.onErrorResponseVerdict(eq(PREPARE_REQUEST), any(OverloadedException.class), eq(0))).thenReturn(RetryVerdict.IGNORE);
CompletionStage<PreparedStatement> prepareFuture = new CqlPrepareHandler(PREPARE_REQUEST, harness.getSession(), harness.getContext(), "test").handle();
// Success on node2, reprepare on node3
assertThatStage(prepareFuture).isFailed(error -> {
assertThat(error).isInstanceOf(IllegalArgumentException.class).hasMessage("IGNORE decisions are not allowed for prepare requests, " + "please fix your retry policy.");
node2Behavior.verifyNoWrite();
node3Behavior.verifyNoWrite();
});
}
}
use of com.datastax.oss.protocol.internal.response.Error in project java-driver by datastax.
the class CqlPrepareHandlerTest method should_retry_initial_prepare_if_recoverable_error.
@Test
public void should_retry_initial_prepare_if_recoverable_error() {
RequestHandlerTestHarness.Builder harnessBuilder = RequestHandlerTestHarness.builder().withResponse(node1, defaultFrameOf(new Error(ProtocolConstants.ErrorCode.OVERLOADED, "mock message"))).withResponse(node2, defaultFrameOf(simplePrepared()));
PoolBehavior node3Behavior = harnessBuilder.customBehavior(node3);
try (RequestHandlerTestHarness harness = harnessBuilder.build()) {
// Make node1's error recoverable, will switch to node2
when(harness.getContext().getRetryPolicy(anyString()).onErrorResponseVerdict(eq(PREPARE_REQUEST), any(OverloadedException.class), eq(0))).thenReturn(RetryVerdict.RETRY_NEXT);
CompletionStage<PreparedStatement> prepareFuture = new CqlPrepareHandler(PREPARE_REQUEST, harness.getSession(), harness.getContext(), "test").handle();
// Success on node2, reprepare on node3
assertThatStage(prepareFuture).isNotDone();
node3Behavior.verifyWrite();
node3Behavior.setWriteSuccess();
node3Behavior.setResponseSuccess(defaultFrameOf(simplePrepared()));
assertThatStage(prepareFuture).isSuccess(CqlPrepareHandlerTest::assertMatchesSimplePrepared);
}
}
use of com.datastax.oss.protocol.internal.response.Error in project java-driver by datastax.
the class CqlRequestHandlerSpeculativeExecutionTest method should_retry_in_speculative_executions.
@Test
@UseDataProvider("idempotentConfig")
public void should_retry_in_speculative_executions(boolean defaultIdempotence, Statement<?> statement) throws Exception {
RequestHandlerTestHarness.Builder harnessBuilder = RequestHandlerTestHarness.builder().withDefaultIdempotence(defaultIdempotence);
PoolBehavior node1Behavior = harnessBuilder.customBehavior(node1);
PoolBehavior node2Behavior = harnessBuilder.customBehavior(node2);
harnessBuilder.withResponse(node3, defaultFrameOf(singleRow()));
try (RequestHandlerTestHarness harness = harnessBuilder.build()) {
SpeculativeExecutionPolicy speculativeExecutionPolicy = harness.getContext().getSpeculativeExecutionPolicy(DriverExecutionProfile.DEFAULT_NAME);
long firstExecutionDelay = 100L;
when(speculativeExecutionPolicy.nextExecution(any(Node.class), eq(null), eq(statement), eq(1))).thenReturn(firstExecutionDelay);
CompletionStage<AsyncResultSet> resultSetFuture = new CqlRequestHandler(statement, harness.getSession(), harness.getContext(), "test").handle();
node1Behavior.verifyWrite();
node1Behavior.setWriteSuccess();
// do not simulate a response from node1. The request will stay hanging for the rest of this
// test
// Discard the timeout task
harness.nextScheduledTimeout();
// next scheduled timeout should be the first speculative execution. Get it and run it.
CapturedTimeout speculativeExecution1 = harness.nextScheduledTimeout();
assertThat(speculativeExecution1.getDelay(TimeUnit.MILLISECONDS)).isEqualTo(firstExecutionDelay);
speculativeExecution1.task().run(speculativeExecution1);
node2Behavior.verifyWrite();
node2Behavior.setWriteSuccess();
// node2 replies with a response that triggers a RETRY_NEXT
node2Behavior.setResponseSuccess(defaultFrameOf(new Error(ProtocolConstants.ErrorCode.IS_BOOTSTRAPPING, "mock message")));
// The second execution should move to node3 and complete the request
assertThatStage(resultSetFuture).isSuccess();
// The request to node1 was still in flight, it should have been cancelled
node1Behavior.verifyCancellation();
}
}
Aggregations