/* * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.retry.stats; import static org.junit.Assert.assertEquals; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.retry.RetryContext; import org.springframework.retry.RetryStatistics; import org.springframework.retry.annotation.CircuitBreaker; import org.springframework.retry.annotation.EnableRetry; import org.springframework.retry.annotation.Recover; import org.springframework.retry.support.RetrySynchronizationManager; /** * @author Dave Syer * */ public class CircuitBreakerInterceptorStatisticsTests { private static final String RECOVERED = "RECOVERED"; private static final String RESULT = "RESULT"; private Service callback; private StatisticsRepository repository; private AnnotationConfigApplicationContext context; @Before public void init() { context = new AnnotationConfigApplicationContext(TestConfiguration.class); this.callback = context.getBean(Service.class); this.repository = context.getBean(StatisticsRepository.class); this.callback.setAttemptsBeforeSuccess(1); } @After public void close() { if (context != null) { context.close(); } } @Test public void testCircuitOpenWhenNotRetryable() throws Throwable { Object result = callback.service("one"); RetryStatistics stats = repository.findOne("test"); // System.err.println(stats); assertEquals(1, stats.getStartedCount()); assertEquals(RECOVERED, result); result = callback.service("two"); assertEquals(RECOVERED, result); assertEquals("There should be two recoveries", 2, stats.getRecoveryCount()); assertEquals("There should only be one error because the circuit is now open", 1, stats.getErrorCount()); } @Configuration @EnableRetry protected static class TestConfiguration { @Bean public StatisticsRepository repository() { return new DefaultStatisticsRepository(); } @Bean public StatisticsListener listener(StatisticsRepository repository) { return new StatisticsListener(repository); } @Bean public Service service() { return new Service(); } } protected static class Service { private int attemptsBeforeSuccess; private Exception exceptionToThrow = new Exception(); private RetryContext status; @CircuitBreaker(label = "test", maxAttempts = 1) public Object service(String input) throws Exception { this.status = RetrySynchronizationManager.getContext(); Integer attempts = (Integer) status.getAttribute("attempts"); if (attempts == null) { attempts = 0; } attempts++; this.status.setAttribute("attempts", attempts); if (attempts <= this.attemptsBeforeSuccess) { throw this.exceptionToThrow; } return RESULT; } @Recover public Object recover() { this.status.setAttribute(RECOVERED, true); return RECOVERED; } public boolean isOpen() { return this.status != null && this.status.getAttribute("open") == Boolean.TRUE; } public void setAttemptsBeforeSuccess(int attemptsBeforeSuccess) { this.attemptsBeforeSuccess = attemptsBeforeSuccess; } public void setExceptionToThrow(Exception exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } } }