@Override public <T> Future<T> invoke( EventLoop eventLoop, URI uri, ClientOptions options, ClientCodec codec, Method method, Object[] args) throws Exception { final CircuitBreaker circuitBreaker; try { circuitBreaker = mapping.get(eventLoop, uri, options, codec, method, args); } catch (Throwable t) { logger.warn("Failed to get a circuit breaker from mapping", t); return delegate().invoke(eventLoop, uri, options, codec, method, args); } if (circuitBreaker.canRequest()) { final Future<T> resultFut = delegate().invoke(eventLoop, uri, options, codec, method, args); resultFut.addListener( future -> { if (future.isSuccess()) { // reports success event circuitBreaker.onSuccess(); } else { circuitBreaker.onFailure(future.cause()); } }); return resultFut; } else { // the circuit is tripped // prepares a failed resultPromise final Promise<T> resultPromise = eventLoop.newPromise(); resultPromise.setFailure(new FailFastException(circuitBreaker)); codec.prepareRequest(method, args, resultPromise); // returns immediately without calling succeeding remote invokers return resultPromise; } }