@Override protected DriftClient<T> get(Injector injector, Annotation clientAnnotation) { DriftClientConfig config = injector.getInstance(Key.get(DriftClientConfig.class, clientAnnotation)); DriftClientFactoryManager<Annotation> driftClientFactoryManager = injector.getInstance(Key.get(DRIFT_CLIENT_FACTORY_MANAGER_TYPE)); AddressSelector<?> addressSelector = injector.getInstance(Key.get(AddressSelector.class, clientAnnotation)); ExceptionClassifier exceptionClassifier = mergeExceptionClassifiers(ImmutableList.<ExceptionClassifier>builder() .addAll(injector.getInstance(Key.get(SET_EXCEPTION_CLASSIFIER_TYPE, clientAnnotation))) // per-client .addAll(injector.getInstance(Key.get(SET_EXCEPTION_CLASSIFIER_TYPE))) // global .build()); List<MethodInvocationFilter> filters = ImmutableList.copyOf(injector.getInstance(Key.get(SET_METHOD_INVOCATION_FILTERS_TYPE, clientAnnotation))); DriftClientFactory driftClientFactory = driftClientFactoryManager.createDriftClientFactory(clientAnnotation, addressSelector, exceptionClassifier); return driftClientFactory.createDriftClient(clientInterface, extractDriftClientBindingAnnotation(clientAnnotation), filters, config); } }
static ExceptionClassifier mergeExceptionClassifiers(Iterable<? extends ExceptionClassifier> classifiers) { List<ExceptionClassifier> exceptionClassifiers = ImmutableList.copyOf(requireNonNull(classifiers, "classifiers is null")); return throwable -> exceptionClassifiers.stream() .map(classifier -> classifier.classifyException(throwable)) .collect(mergeExceptionClassifications()); }
@Override protected DriftClient<T> get(Injector injector, Annotation clientAnnotation) { DriftClientConfig config = injector.getInstance(Key.get(DriftClientConfig.class, clientAnnotation)); DriftClientFactoryManager<Annotation> driftClientFactoryManager = injector.getInstance(Key.get(DRIFT_CLIENT_FACTORY_MANAGER_TYPE)); AddressSelector<?> addressSelector = injector.getInstance(Key.get(AddressSelector.class, clientAnnotation)); ExceptionClassifier exceptionClassifier = mergeExceptionClassifiers(ImmutableList.<ExceptionClassifier>builder() .addAll(injector.getInstance(Key.get(SET_EXCEPTION_CLASSIFIER_TYPE, clientAnnotation))) // per-client .addAll(injector.getInstance(Key.get(SET_EXCEPTION_CLASSIFIER_TYPE))) // global .build()); List<MethodInvocationFilter> filters = ImmutableList.copyOf(injector.getInstance(Key.get(SET_METHOD_INVOCATION_FILTERS_TYPE, clientAnnotation))); DriftClientFactory driftClientFactory = driftClientFactoryManager.createDriftClientFactory(clientAnnotation, addressSelector, exceptionClassifier); return driftClientFactory.createDriftClient(clientInterface, extractDriftClientBindingAnnotation(clientAnnotation), filters, config); } }
static ExceptionClassifier mergeExceptionClassifiers(Iterable<? extends ExceptionClassifier> classifiers) { List<ExceptionClassifier> exceptionClassifiers = ImmutableList.copyOf(requireNonNull(classifiers, "classifiers is null")); return throwable -> exceptionClassifiers.stream() .map(classifier -> classifier.classifyException(throwable)) .collect(mergeExceptionClassifications()); }
@Test public void testInvoker() throws Exception { ResultsSupplier resultsSupplier = new ResultsSupplier(); MockMethodInvokerFactory<String> methodInvokerFactory = new MockMethodInvokerFactory<>(resultsSupplier); TestingMethodInvocationStatsFactory statsFactory = new TestingMethodInvocationStatsFactory(); List<TestingExceptionClassifier> classifiers = ImmutableList.of(new TestingExceptionClassifier(), new TestingExceptionClassifier(), new TestingExceptionClassifier()); DriftClientFactoryManager<String> clientFactoryManager = new DriftClientFactoryManager<>(codecManager, methodInvokerFactory, statsFactory); DriftClientFactory driftClientFactory = clientFactoryManager.createDriftClientFactory("clientIdentity", new MockAddressSelector(), mergeExceptionClassifiers(classifiers)); DriftClient<Client> driftClient = driftClientFactory.createDriftClient(Client.class, Optional.empty(), ImmutableList.of(), new DriftClientConfig()); Client client = driftClient.get(ADDRESS_SELECTION_CONTEXT, HEADERS); assertEquals(methodInvokerFactory.getClientIdentity(), "clientIdentity"); testClient(resultsSupplier, ImmutableList.of(methodInvokerFactory.getMethodInvoker()), classifiers, statsFactory, client, Optional.empty()); }
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; }
@Test public void testFilter() throws Exception { ResultsSupplier resultsSupplier = new ResultsSupplier(); PassThroughFilter passThroughFilter = new PassThroughFilter(); ShortCircuitFilter shortCircuitFilter = new ShortCircuitFilter(resultsSupplier); MockMethodInvokerFactory<String> invokerFactory = new MockMethodInvokerFactory<>(resultsSupplier); TestingMethodInvocationStatsFactory statsFactory = new TestingMethodInvocationStatsFactory(); List<TestingExceptionClassifier> classifiers = ImmutableList.of(new TestingExceptionClassifier(), new TestingExceptionClassifier(), new TestingExceptionClassifier()); DriftClientFactoryManager<String> clientFactoryManager = new DriftClientFactoryManager<>(codecManager, invokerFactory, statsFactory); DriftClientFactory driftClientFactory = clientFactoryManager.createDriftClientFactory("clientIdentity", new MockAddressSelector(), mergeExceptionClassifiers(classifiers)); DriftClient<Client> driftClient = driftClientFactory.createDriftClient( Client.class, Optional.empty(), ImmutableList.of(passThroughFilter, shortCircuitFilter), new DriftClientConfig()); Client client = driftClient.get(ADDRESS_SELECTION_CONTEXT, HEADERS); assertEquals(invokerFactory.getClientIdentity(), "clientIdentity"); testClient(resultsSupplier, ImmutableList.of(passThroughFilter, shortCircuitFilter), classifiers, statsFactory, client, Optional.empty()); }
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; }