@Test public void testFallback() { HystrixCommand<Integer> superCmd = new SuperCommand("cache", false); assertEquals(2, superCmd.execute().intValue()); HystrixCommand<Integer> subNoOverridesCmd = new SubCommandNoOverride("cache", false); assertEquals(2, subNoOverridesCmd.execute().intValue()); HystrixCommand<Integer> subOverriddenFallbackCmd = new SubCommandOverrideFallback("cache", false); assertEquals(3, subOverriddenFallbackCmd.execute().intValue()); }
public R doGetFallback() { return super.getFallback(); }
Observable<Boolean> o = cmd.toObservable(); Subscription s = o. doOnUnsubscribe(new Action0() { assertTrue(latch.await(200, TimeUnit.MILLISECONDS)); System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); assertEquals("Number of execution semaphores in use", 0, cmd.getExecutionSemaphore().getNumberOfPermitsUsed()); assertEquals("Number of fallback semaphores in use", 0, cmd.getFallbackSemaphore().getNumberOfPermitsUsed()); assertFalse(cmd.isExecutionComplete()); assertEquals(null, cmd.getFailedExecutionException()); assertNull(cmd.getExecutionException()); System.out.println("Execution time : " + cmd.getExecutionTimeInMilliseconds()); assertTrue(cmd.getExecutionTimeInMilliseconds() > -1); assertFalse(cmd.isSuccessfulExecution()); assertCommandExecutionEvents(cmd, HystrixEventType.CANCELLED); assertEquals(0, cmd.metrics.getCurrentConcurrentExecutionCount());
/** * Used for synchronous execution of command. * * @return R * Result of {@link #run()} execution or a fallback from {@link #getFallback()} if the command fails for any reason. * @throws HystrixRuntimeException * if a failure occurs and a fallback cannot be retrieved * @throws HystrixBadRequestException * if invalid arguments or state were used representing a user failure, not a system failure * @throws IllegalStateException * if invoked more than once */ public R execute() { try { return queue().get(); } catch (Exception e) { throw Exceptions.sneakyThrow(decomposeException(e)); } }
@Override public Observable<BatchReturnType> createObservableCommand(Collection<CollapsedRequest<ResponseType, RequestArgumentType>> requests) { final HystrixCommand<BatchReturnType> command = self.createCommand(requests); command.markAsCollapsedCommand(this.getCollapserKey(), requests.size()); self.metrics.markBatch(requests.size()); return command.toObservable(); }
@Override public boolean cancel(boolean mayInterruptIfRunning) { if (delegate.isCancelled()) { return false; } if (HystrixCommand.this.getProperties().executionIsolationThreadInterruptOnFutureCancel().get()) { /* * The only valid transition here is false -> true. If there are two futures, say f1 and f2, created by this command * (which is super-weird, but has never been prohibited), and calls to f1.cancel(true) and to f2.cancel(false) are * issued by different threads, it's unclear about what value would be used by the time mayInterruptOnCancel is checked. * The most consistent way to deal with this scenario is to say that if *any* cancellation is invoked with interruption, * than that interruption request cannot be taken back. */ interruptOnFutureCancel.compareAndSet(false, mayInterruptIfRunning); } final boolean res = delegate.cancel(interruptOnFutureCancel.get()); if (!isExecutionComplete() && interruptOnFutureCancel.get()) { final Thread t = executionThread.get(); if (t != null && !t.equals(Thread.currentThread())) { t.interrupt(); } } return res; }
@Override protected Object getFallback() { if (fallbackFactory == null) { return super.getFallback(); Object result = fallbackMethodMap.get(method).invoke(fallback, args); if (isReturnsHystrixCommand(method)) { return ((HystrixCommand) result).execute(); } else if (isReturnsObservable(method)) {
/** * Tests that the circuit-breaker reports itself as "OPEN" if set as forced-open */ @Test public void testCircuitBreakerReportsOpenIfForcedOpen() { HystrixCommand<Boolean> cmd = new HystrixCommand<Boolean>(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GROUP")).andCommandPropertiesDefaults(new HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(true))) { @Override protected Boolean run() throws Exception { return true; } @Override protected Boolean getFallback() { return false; } }; assertFalse(cmd.execute()); //fallback should fire System.out.println("RESULT : " + cmd.getExecutionEvents()); assertTrue(cmd.isCircuitBreakerOpen()); }
@Override protected Boolean run() { assertEquals("OuterCommand", Hystrix.getCurrentThreadExecutingCommand().name()); System.out.println("Outer Thread : " + Thread.currentThread().getName()); //should be a single execution on this thread assertEquals(1, Hystrix.getCommandCount()); if (Hystrix.getCurrentThreadExecutingCommand() == null) { throw new RuntimeException("BEFORE expected it to run inside a thread"); } HystrixCommand<Boolean> command2 = new HystrixCommand<Boolean>(Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey("TestUtil")) .andCommandKey(HystrixCommandKey.Factory.asKey("InnerCommand"))) { @Override protected Boolean run() { assertEquals("InnerCommand", Hystrix.getCurrentThreadExecutingCommand().name()); System.out.println("Inner Thread : " + Thread.currentThread().getName()); //should be a single execution on this thread, since outer/inner are on different threads assertEquals(1, Hystrix.getCommandCount()); return Hystrix.getCurrentThreadExecutingCommand() != null; } }; if (Hystrix.getCurrentThreadExecutingCommand() == null) { throw new RuntimeException("AFTER expected it to run inside a thread"); } return command2.execute(); }
HystrixCommand<Boolean> cmd3 = new FailureCommand(key, 1, sleepWindow); HystrixCommand<Boolean> cmd4 = new FailureCommand(key, 1, sleepWindow); cmd1.execute(); cmd2.execute(); cmd3.execute(); cmd4.execute(); Observable<Boolean> o = cmd5.observe(); Subscription s = o.subscribe(); s.unsubscribe(); cmd6.execute();
cmd1.execute(); HystrixCommand<Boolean> cmd2 = new SuccessCommand(key, 1); cmd2.execute(); HystrixCommand<Boolean> cmd3 = new FailureCommand(key, 1); cmd3.execute(); HystrixCommand<Boolean> cmd4 = new SuccessCommand(key, 1); cmd4.execute(); HystrixCommand<Boolean> cmd5 = new SuccessCommand(key, 1); cmd5.execute(); HystrixCommand<Boolean> cmd6 = new FailureCommand(key, 1); cmd6.execute(); HystrixCommand<Boolean> cmd7 = new SuccessCommand(key, 1); cmd7.execute(); HystrixCommand<Boolean> cmd8 = new FailureCommand(key, 1); cmd8.execute(); System.out.println("Current CircuitBreaker Status : " + cmd1.getMetrics().getHealthCounts()); assertTrue(cb.allowRequest()); assertFalse(cb.isOpen());
assertFalse(cb.isOpen()); cmd1.execute(); HystrixCommand<Boolean> cmd2 = new FailureCommand(key, 1, sleepWindow); cmd2.execute(); HystrixCommand<Boolean> cmd3 = new FailureCommand(key, 1, sleepWindow); cmd3.execute(); HystrixCommand<Boolean> cmd4 = new TimeoutCommand(key, sleepWindow); cmd4.execute(); System.out.println("CircuitBreaker state 1 : " + cmd1.getMetrics().getHealthCounts()); assertTrue(cb.isOpen()); Observable<Boolean> asyncResult = cmd5.observe(); System.out.println("CircuitBreaker state 2 : " + cmd1.getMetrics().getHealthCounts()); assertTrue(cb.allowRequest()); assertTrue(cb.allowRequest());
return hystrixCommand.execute(); } else if (isReturnsHystrixCommand(method)) { return hystrixCommand; } else if (isReturnsObservable(method)) { return hystrixCommand.toObservable(); } else if (isReturnsSingle(method)) { return hystrixCommand.toObservable().toSingle(); } else if (isReturnsCompletable(method)) { return hystrixCommand.toObservable().toCompletable(); return hystrixCommand.execute();
@Test public void testExecutionTimeoutValue() { HystrixCommand.Setter properties = HystrixCommand.Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey("TestKey")) .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() .withExecutionTimeoutInMilliseconds(50)); HystrixCommand<String> command = new HystrixCommand<String>(properties) { @Override protected String run() throws Exception { Thread.sleep(3000); // should never reach here return "hello"; } @Override protected String getFallback() { if (isResponseTimedOut()) { return "timed-out"; } else { return "abc"; } } }; String value = command.execute(); assertTrue(command.isResponseTimedOut()); assertEquals("expected fallback value", "timed-out", value); }
Observable<Boolean> o = cmd.observe(); Subscription s = o. doOnUnsubscribe(new Action0() { assertTrue(latch.await(200, TimeUnit.MILLISECONDS)); System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); assertEquals("Number of execution semaphores in use", 0, cmd.getExecutionSemaphore().getNumberOfPermitsUsed()); assertEquals("Number of fallback semaphores in use", 0, cmd.getFallbackSemaphore().getNumberOfPermitsUsed()); assertFalse(cmd.isExecutionComplete()); assertEquals(null, cmd.getFailedExecutionException()); assertNull(cmd.getExecutionException()); assertTrue(cmd.getExecutionTimeInMilliseconds() > -1); assertFalse(cmd.isSuccessfulExecution()); assertCommandExecutionEvents(cmd, HystrixEventType.CANCELLED); assertEquals(0, cmd.metrics.getCurrentConcurrentExecutionCount());
Observable<Boolean> o = cmd.toObservable(); Subscription s = o. doOnUnsubscribe(new Action0() { s.unsubscribe(); assertTrue(latch.await(200, TimeUnit.MILLISECONDS)); assertEquals("Number of execution semaphores in use", 0, cmd.getExecutionSemaphore().getNumberOfPermitsUsed()); assertEquals("Number of fallback semaphores in use", 0, cmd.getFallbackSemaphore().getNumberOfPermitsUsed()); assertEquals(0, cmd.metrics.getCurrentConcurrentExecutionCount()); assertFalse(cmd.isExecutionComplete()); } catch (InterruptedException ex) { ex.printStackTrace();
@Test public void testRxRetry() throws Exception { // see https://github.com/Netflix/Hystrix/issues/1100 // Since each command instance is single-use, the expectation is that applying the .retry() operator // results in only a single execution and propagation out of that error HystrixCommand<Integer> cmd = getLatentCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.FAILURE, 300, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED, 100); final CountDownLatch latch = new CountDownLatch(1); System.out.println(System.currentTimeMillis() + " : Starting"); Observable<Integer> o = cmd.toObservable().retry(2); System.out.println(System.currentTimeMillis() + " Created retried command : " + o); o.subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " : OnCompleted"); latch.countDown(); } @Override public void onError(Throwable e) { System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " : OnError : " + e); latch.countDown(); } @Override public void onNext(Integer integer) { System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " : OnNext : " + integer); } }); latch.await(1000, TimeUnit.MILLISECONDS); System.out.println(System.currentTimeMillis() + " ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); }
final Future<R> delegate = toObservable().toBlocking().toFuture(); return f; } catch (Exception e) { Throwable t = decomposeException(e); if (t instanceof HystrixBadRequestException) { return f;
HystrixCommand<Integer> cmd = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS, 100, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED); Observable<Integer> o = cmd.toObservable() .doOnNext(new Action1<Integer>() { @Override assertTrue(cmd.isExecutedInThread()); assertCommandExecutionEvents(cmd, HystrixEventType.SUCCESS);
/** * Copies various parameters like execution events,time and any exception after command execution.<br/><br/> * <b>Should be called only after execution of command completes</b> * @param executor Executor used to execute this request. * @return */ @SuppressWarnings({ "rawtypes", "unchecked" }) public Builder withCommandData(Executor executor) { HystrixCommand command = (HystrixCommand) executor; withEventList(command.getExecutionEvents()) .withExecutionTime(command.getExecutionTimeInMilliseconds()) .withException((Exception) command.getFailedExecutionException()); return this; }