/** * Checks if Cassandra table absence error occur. * * @param e Exception to check. * @return {@code true} in case of table absence error. */ public static boolean isTableAbsenceError(Throwable e) { while (e != null) { if (e instanceof InvalidQueryException && (TABLE_EXIST_ERROR1.matcher(e.getMessage()).matches() || TABLE_EXIST_ERROR3.matcher(e.getMessage()).matches() || KEYSPACE_EXIST_ERROR1.matcher(e.getMessage()).matches() || KEYSPACE_EXIST_ERROR2.matcher(e.getMessage()).matches())) return true; if (e instanceof NoHostAvailableException && ((NoHostAvailableException) e).getErrors() != null) { NoHostAvailableException ex = (NoHostAvailableException)e; for (Map.Entry<InetSocketAddress, Throwable> entry : ex.getErrors().entrySet()) { Throwable error = entry.getValue(); if (error instanceof DriverException && (error.getMessage().contains(TABLE_EXIST_ERROR2) || KEYSPACE_EXIST_ERROR3.matcher(error.getMessage()).matches())) return true; } } e = e.getCause(); } return false; }
/** * Tests the NoHostAvailableException. by attempting to build a cluster using the IP address * "255.255.255.255" and test all available exception methods. */ @Test(groups = "short") public void noHostAvailableException() throws Exception { try { Cluster.builder().addContactPoints("255.255.255.255").build(); } catch (NoHostAvailableException e) { assertEquals(e.getErrors().size(), 1); assertTrue( e.getErrors() .values() .iterator() .next() .toString() .contains("[/255.255.255.255] Cannot connect")); NoHostAvailableException copy = (NoHostAvailableException) e.copy(); assertEquals(copy.getMessage(), e.getMessage()); assertEquals(copy.getErrors(), e.getErrors()); } }
@Test(groups = "short") public void should_fail_if_host_is_not_connected() { // given a statement with host explicitly set that for which we have no active pool. Host host4 = TestUtils.findHost(cluster, 4); Statement statement = new SimpleStatement("select * system.local").setHost(host4); try { // when statement is executed session.execute(statement); fail("Query should have failed"); } catch (NoHostAvailableException e) { // then the request should fail with a NHAE and no host was tried. assertThat(e.getErrors()).isEmpty(); } finally { verifyNoLbpInteractions(); } } }
assertThat(((NoHostAvailableException) e).getErrors().get(hostAddress)) .isInstanceOf(expectedException); } else {
@SuppressWarnings("UnusedParameters") @Test(groups = "short", dataProvider = "serverSideErrors") public void should_retry_on_server_error_if_statement_idempotent( Result error, Class<? extends DriverException> exception) { simulateError(1, error); simulateError(2, error); simulateError(3, error); try { session.execute(new SimpleStatement("mock query").setIdempotent(true)); fail("expected a NoHostAvailableException"); } catch (NoHostAvailableException e) { assertThat(e.getErrors().keySet()) .hasSize(3) .containsOnly( host1.getSocketAddress(), host2.getSocketAddress(), host3.getSocketAddress()); assertThat(e.getErrors().values()).hasOnlyElementsOfType(exception); } assertOnRequestErrorWasCalled(3, exception); assertThat(errors.getOthers().getCount()).isEqualTo(3); assertThat(errors.getRetries().getCount()).isEqualTo(3); assertThat(errors.getRetriesOnOtherErrors().getCount()).isEqualTo(3); assertQueried(1, 1); assertQueried(2, 1); assertQueried(3, 1); }
@Test(groups = "short", dataProvider = "serverSideErrors") public void should_try_next_host_on_server_side_error( Result error, Class<? extends DriverException> exception) { simulateError(1, error); simulateError(2, error); simulateError(3, error); try { query(); Fail.fail("expected a NoHostAvailableException"); } catch (NoHostAvailableException e) { assertThat(e.getErrors().keySet()) .hasSize(3) .containsOnly( host1.getSocketAddress(), host2.getSocketAddress(), host3.getSocketAddress()); assertThat(e.getErrors().values()).hasOnlyElementsOfType(exception); } assertOnRequestErrorWasCalled(3, exception); assertThat(errors.getOthers().getCount()).isEqualTo(3); assertThat(errors.getRetries().getCount()).isEqualTo(3); assertThat(errors.getRetriesOnOtherErrors().getCount()).isEqualTo(3); assertQueried(1, 1); assertQueried(2, 1); assertQueried(3, 1); }
@Test(groups = "short", dataProvider = "connectionErrors") public void should_try_next_host_on_connection_error(ClosedConnectionConfig.CloseType closeType) { simulateError(1, closed_connection, new ClosedConnectionConfig(closeType)); simulateError(2, closed_connection, new ClosedConnectionConfig(closeType)); simulateError(3, closed_connection, new ClosedConnectionConfig(closeType)); try { query(); Fail.fail("expected a NoHostAvailableException"); } catch (NoHostAvailableException e) { assertThat(e.getErrors().keySet()) .hasSize(3) .containsOnly( host1.getSocketAddress(), host2.getSocketAddress(), host3.getSocketAddress()); assertThat(e.getErrors().values()).hasOnlyElementsOfType(TransportException.class); } assertOnRequestErrorWasCalled(3, TransportException.class); assertThat(errors.getRetries().getCount()).isEqualTo(3); assertThat(errors.getConnectionErrors().getCount()).isEqualTo(3); assertThat(errors.getIgnoresOnConnectionError().getCount()).isEqualTo(0); assertThat(errors.getRetriesOnConnectionError().getCount()).isEqualTo(3); assertQueried(1, 1); assertQueried(2, 1); assertQueried(3, 1); }
@Test(groups = "short", dataProvider = "connectionErrors") public void should_retry_on_connection_error_if_statement_idempotent( ClosedConnectionConfig.CloseType closeType) { simulateError(1, closed_connection, new ClosedConnectionConfig(closeType)); simulateError(2, closed_connection, new ClosedConnectionConfig(closeType)); simulateError(3, closed_connection, new ClosedConnectionConfig(closeType)); try { session.execute(new SimpleStatement("mock query").setIdempotent(true)); Fail.fail("expected a TransportException"); } catch (NoHostAvailableException e) { assertThat(e.getErrors().keySet()) .hasSize(3) .containsOnly( host1.getSocketAddress(), host2.getSocketAddress(), host3.getSocketAddress()); assertThat(e.getErrors().values()).hasOnlyElementsOfType(TransportException.class); } assertOnRequestErrorWasCalled(3, TransportException.class); assertThat(errors.getRetries().getCount()).isEqualTo(3); assertThat(errors.getConnectionErrors().getCount()).isEqualTo(3); assertThat(errors.getIgnoresOnConnectionError().getCount()).isEqualTo(0); assertThat(errors.getRetriesOnConnectionError().getCount()).isEqualTo(3); assertQueried(1, 1); assertQueried(2, 1); assertQueried(3, 1); }
/** * Ensures that when handling a connection error caused by the connection closing during a request * in a way described by {@link #connectionErrors} that the next host is tried. * * @param closeType The way the connection should be closed during the request. */ @Test(groups = "short", dataProvider = "connectionErrors") public void should_try_next_host_on_connection_error(ClosedConnectionConfig.CloseType closeType) { simulateError(1, closed_connection, new ClosedConnectionConfig(closeType)); simulateError(2, closed_connection, new ClosedConnectionConfig(closeType)); simulateError(3, closed_connection, new ClosedConnectionConfig(closeType)); try { query(); Fail.fail("expected a TransportException"); } catch (NoHostAvailableException e) { assertThat(e.getErrors().keySet()) .hasSize(3) .containsOnly( host1.getSocketAddress(), host2.getSocketAddress(), host3.getSocketAddress()); assertThat(e.getErrors().values()).hasOnlyElementsOfType(TransportException.class); } assertOnRequestErrorWasCalled(3, TransportException.class); assertThat(errors.getRetries().getCount()).isEqualTo(3); assertThat(errors.getConnectionErrors().getCount()).isEqualTo(3); assertThat(errors.getIgnoresOnConnectionError().getCount()).isEqualTo(0); assertThat(errors.getRetriesOnConnectionError().getCount()).isEqualTo(3); assertQueried(1, 1); assertQueried(2, 1); assertQueried(3, 1); }
@Test(groups = "short") public void should_fail_if_host_fails_query() { String query = "mock"; sCluster .node(1) .primingClient() .prime( PrimingRequest.queryBuilder() .withQuery(query) .withThen(then().withResult(Result.unavailable)) .build()); // given a statement with a host configured to fail the given query. Host host1 = TestUtils.findHost(cluster, 1); Statement statement = new SimpleStatement(query).setHost(host1); try { // when statement is executed an error should be raised. session.execute(statement); fail("Query should have failed"); } catch (NoHostAvailableException e) { // then the request should fail with a NHAE and no host was tried. assertThat(e.getErrors()).hasSize(1); assertThat(e.getErrors().values().iterator().next()).isInstanceOf(UnavailableException.class); } finally { verifyNoLbpInteractions(); } }
/** * Returns true if the exception is one which indicates that the frame size may be too large, false otherwise. */ private static boolean isAdaptiveException(Throwable t) { if (t instanceof FrameTooLongException) { return true; } if (t instanceof NoHostAvailableException) { // If the issue on every host is adaptive then the exception is adaptive Collection<Throwable> hostExceptions = ((NoHostAvailableException) t).getErrors().values(); return !hostExceptions.isEmpty() && hostExceptions.stream().allMatch(AdaptiveResultSet::isAdaptiveException); } return false; }
/** * Returns true if the exception is one which indicates that the frame size may be too large, false otherwise. */ private static boolean isAdaptiveException(Throwable t) { if (t instanceof FrameTooLongException) { return true; } if (t instanceof NoHostAvailableException) { // If the issue on every host is adaptive then the exception is adaptive Collection<Throwable> hostExceptions = ((NoHostAvailableException) t).getErrors().values(); return !hostExceptions.isEmpty() && hostExceptions.stream().allMatch(AdaptiveResultSet::isAdaptiveException); } return false; }
} catch (NoHostAvailableException nhae) { Collection<Throwable> errors = nhae.getErrors().values(); assertThat(errors).hasSize(1); Throwable e = errors.iterator().next();
private boolean canRetryDriverConnection(Exception e) { if (e instanceof DriverException && e.getMessage().contains("Connection thread interrupted")) return true; if (e instanceof NoHostAvailableException) { if (((NoHostAvailableException) e).getErrors().values().size() == 1) { Throwable cause = ((NoHostAvailableException) e).getErrors().values().iterator().next(); if (cause != null && cause.getCause() instanceof java.nio.channels.ClosedByInterruptException) { return true; } } } return false; } }
} catch (NoHostAvailableException e) { Throwable error = e.getErrors().get(host1.getSocketAddress()); assertThat(error).isNotNull(); assertThat(error).isInstanceOf(UnavailableException.class);
private boolean canRetryDriverConnection(Exception e) { if (e instanceof DriverException && e.getMessage().contains("Connection thread interrupted")) return true; if (e instanceof NoHostAvailableException) { if (((NoHostAvailableException) e).getErrors().values().size() == 1) { Throwable cause = ((NoHostAvailableException) e).getErrors().values().iterator().next(); if (cause != null && cause.getCause() instanceof java.nio.channels.ClosedByInterruptException) { return true; } } } return false; } }
} catch (NoHostAvailableException e) { Throwable error = e.getErrors().get(hostAddress); assertThat(error).isNotNull(); assertThat(error).isInstanceOf(UnavailableException.class);
Assertions.fail("expected a NoHostAvailableException"); } catch (NoHostAvailableException e) { assertThat(e.getErrors().keySet()) .hasSize(3) .containsOnly( host1.getSocketAddress(), host2.getSocketAddress(), host3.getSocketAddress()); assertThat(e.getErrors().values()) .hasOnlyElementsOfType(OperationTimedOutException.class) .extractingResultOf("getMessage")
fail("expected a NoHostAvailableException"); } catch (NoHostAvailableException e) { assertThat(e.getErrors().keySet()) .hasSize(3) .containsOnly( host1.getSocketAddress(), host2.getSocketAddress(), host3.getSocketAddress()); assertThat(e.getErrors().values()) .hasOnlyElementsOfType(OperationTimedOutException.class) .extractingResultOf("getMessage")