@Override public void configure(Binder binder) { driftClientBinder(binder) .bindDriftClient(PrestoThriftService.class) .withExceptionClassifier(t -> { if (t instanceof PrestoThriftServiceException) { boolean retryable = ((PrestoThriftServiceException) t).isRetryable(); return new ExceptionClassification(Optional.of(retryable), HostStatus.NORMAL); } return NORMAL_EXCEPTION; }); binder.bind(ThriftConnector.class).in(Scopes.SINGLETON); binder.bind(ThriftMetadata.class).in(Scopes.SINGLETON); binder.bind(ThriftSplitManager.class).in(Scopes.SINGLETON); binder.bind(ThriftPageSourceProvider.class).in(Scopes.SINGLETON); configBinder(binder).bindConfig(ThriftConnectorConfig.class); binder.bind(ThriftSessionProperties.class).in(Scopes.SINGLETON); binder.bind(ThriftIndexProvider.class).in(Scopes.SINGLETON); binder.bind(ThriftConnectorStats.class).in(Scopes.SINGLETON); newExporter(binder).export(ThriftConnectorStats.class) .as(generatedNameOf(ThriftConnectorStats.class, connectorId)); }
public ExceptionClassification toExceptionClassification() { return new ExceptionClassification(retry, hostStatus); }
public ExceptionClassification toExceptionClassification() { return new ExceptionClassification(retry, hostStatus); }
public ExceptionClassification classifyException(Throwable throwable, boolean idempotent) { if (throwable instanceof ConnectionFailedException) { return new ExceptionClassification(Optional.of(TRUE), DOWN); } if (idempotent && throwable instanceof RequestTimeoutException) { // We don't know if the server is overloaded, or if this specific // request just takes to long, so just mark the server as normal. return new ExceptionClassification(Optional.of(TRUE), NORMAL); } if (throwable instanceof MessageTooLargeException) { return new ExceptionClassification(Optional.of(FALSE), NORMAL); } // interrupted exceptions are always an immediate failure if (throwable instanceof InterruptedException || throwable instanceof InterruptedIOException) { return new ExceptionClassification(Optional.of(FALSE), NORMAL); } // allow classifier to return a hard result ExceptionClassification result = exceptionClassifier.classifyException(unwrapUserException(throwable)); if (result.isRetry().isPresent()) { return result; } if (idempotent && throwable instanceof TTransportException) { // We don't know if there is a problem with this server or if this // is a general network error, so just mark the server as normal. return new ExceptionClassification(Optional.of(TRUE), NORMAL); } return result; }
public ExceptionClassification classifyException(Throwable throwable, boolean idempotent) { if (throwable instanceof ConnectionFailedException) { return new ExceptionClassification(Optional.of(TRUE), DOWN); } if (idempotent && throwable instanceof RequestTimeoutException) { // We don't know if the server is overloaded, or if this specific // request just takes to long, so just mark the server as normal. return new ExceptionClassification(Optional.of(TRUE), NORMAL); } if (throwable instanceof MessageTooLargeException) { return new ExceptionClassification(Optional.of(FALSE), NORMAL); } // interrupted exceptions are always an immediate failure if (throwable instanceof InterruptedException || throwable instanceof InterruptedIOException) { return new ExceptionClassification(Optional.of(FALSE), NORMAL); } // allow classifier to return a hard result ExceptionClassification result = exceptionClassifier.classifyException(unwrapUserException(throwable)); if (result.isRetry().isPresent()) { return result; } if (idempotent && throwable instanceof TTransportException) { // We don't know if there is a problem with this server or if this // is a general network error, so just mark the server as normal. return new ExceptionClassification(Optional.of(TRUE), NORMAL); } return result; }
@Override public ExceptionClassification classifyException(Throwable throwable) { lastException.set(throwable); return new ExceptionClassification(Optional.of(false), NORMAL); } }
@Override public void configure(Binder binder) { driftClientBinder(binder) .bindDriftClient(PrestoThriftService.class) .withExceptionClassifier(t -> { if (t instanceof PrestoThriftServiceException) { boolean retryable = ((PrestoThriftServiceException) t).isRetryable(); return new ExceptionClassification(Optional.of(retryable), HostStatus.NORMAL); } return NORMAL_EXCEPTION; }); binder.bind(ThriftConnector.class).in(Scopes.SINGLETON); binder.bind(ThriftMetadata.class).in(Scopes.SINGLETON); binder.bind(ThriftSplitManager.class).in(Scopes.SINGLETON); binder.bind(ThriftPageSourceProvider.class).in(Scopes.SINGLETON); configBinder(binder).bindConfig(ThriftConnectorConfig.class); binder.bind(ThriftSessionProperties.class).in(Scopes.SINGLETON); binder.bind(ThriftIndexProvider.class).in(Scopes.SINGLETON); binder.bind(ThriftConnectorStats.class).in(Scopes.SINGLETON); newExporter(binder).export(ThriftConnectorStats.class).withGeneratedName(); }
public static Exception createClassifiedException(boolean retry, HostStatus hostStatus, boolean wrapWithApplicationException) { Exception exception = new ClassifiedException(new ExceptionClassification(Optional.of(retry), hostStatus)); if (wrapWithApplicationException) { exception = new DriftApplicationException(exception); } return exception; }
@Test(timeOut = 60000) public void testMaxRetries() throws Exception { int maxRetries = 5; RetryPolicy retryPolicy = new RetryPolicy(new DriftClientConfig().setMaxRetries(maxRetries), new TestingExceptionClassifier()); TestingMethodInvocationStat stat = new TestingMethodInvocationStat(); AtomicInteger attempts = new AtomicInteger(); DriftMethodInvocation<?> methodInvocation = createDriftMethodInvocation(retryPolicy, stat, () -> { attempts.getAndIncrement(); return immediateFailedFuture(createClassifiedException(true, NORMAL)); }); try { methodInvocation.get(); fail("Expected exception"); } catch (ExecutionException e) { assertEquals(attempts.get(), maxRetries + 1); assertClassifiedException(e.getCause(), new ExceptionClassification(Optional.of(true), NORMAL), maxRetries); } stat.assertFailure(maxRetries); }
@Test(timeOut = 60000) public void testBasicRetriesToNoHosts() throws Exception { RetryPolicy retryPolicy = new RetryPolicy(new DriftClientConfig().setMaxRetries(10), new TestingExceptionClassifier()); TestingMethodInvocationStat stat = new TestingMethodInvocationStat(); AtomicInteger attempts = new AtomicInteger(); int expectedRetries = 3; DriftMethodInvocation<?> methodInvocation = createDriftMethodInvocation( retryPolicy, stat, new MockMethodInvoker(() -> { attempts.getAndIncrement(); return immediateFailedFuture(createClassifiedException(true, NORMAL)); }), new TestingAddressSelector(expectedRetries + 1), systemTicker()); try { methodInvocation.get(); fail("Expected exception"); } catch (ExecutionException e) { assertEquals(attempts.get(), expectedRetries + 1); assertClassifiedException(e.getCause(), new ExceptionClassification(Optional.of(true), NORMAL), expectedRetries); } stat.assertFailure(expectedRetries); }
@Test public void testRetryUserException() { ExceptionClassification overloaded = new ExceptionClassification(Optional.of(true), OVERLOADED); RetryPolicy policy = new RetryPolicy(new DriftClientConfig(), classifier -> { if (classifier instanceof TestingUserException) { return overloaded; } return NORMAL_EXCEPTION; }); assertSame(policy.classifyException(new DriftApplicationException(new TestingUserException()), true), overloaded); assertSame(policy.classifyException(new TestingUserException(), true), overloaded); }
assertClassifiedException(e.getCause(), new ExceptionClassification(Optional.of(true), NORMAL), maxRetries);
assertClassifiedException(e.getCause(), new ExceptionClassification(Optional.of(false), NORMAL), expectedRetries);
if (t instanceof ExampleException) { boolean retryable = ((ExampleException) t).isRetryable(); return new ExceptionClassification(Optional.of(retryable), NORMAL);