Repository: james-project
Updated Branches:
  refs/heads/master b0d35b70b -> 2a4984533


JAMES-1999 New util for retry executor


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/6c5912f1
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/6c5912f1
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/6c5912f1

Branch: refs/heads/master
Commit: 6c5912f16d6a352b8a501cb11efcf4d39daf2c41
Parents: b0d35b7
Author: quynhn <qngu...@linagora.com>
Authored: Fri Apr 14 09:47:30 2017 +0700
Committer: benwa <btell...@linagora.com>
Committed: Fri Apr 21 07:51:48 2017 +0700

----------------------------------------------------------------------
 server/container/guice/guice-common/pom.xml     |   9 ++
 .../apache/james/utils/RetryExecutorUtil.java   |  38 ++++++
 .../org/apache/james/utils/FaultyService.java   |  24 ++++
 .../james/utils/RetryExecutorUtilTest.java      | 124 +++++++++++++++++++
 4 files changed, 195 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/6c5912f1/server/container/guice/guice-common/pom.xml
----------------------------------------------------------------------
diff --git a/server/container/guice/guice-common/pom.xml 
b/server/container/guice/guice-common/pom.xml
index 3186b34..4f63bfa 100644
--- a/server/container/guice/guice-common/pom.xml
+++ b/server/container/guice/guice-common/pom.xml
@@ -277,6 +277,10 @@
                     <scope>test</scope>
                 </dependency>
                 <dependency>
+                    <groupId>com.nurkiewicz.asyncretry</groupId>
+                    <artifactId>asyncretry</artifactId>
+                </dependency>
+                <dependency>
                     <groupId>org.assertj</groupId>
                     <artifactId>assertj-core</artifactId>
                     <version>${assertj-3.version}</version>
@@ -289,6 +293,11 @@
                     <type>test-jar</type>
                 </dependency>
                 <dependency>
+                    <groupId>org.mockito</groupId>
+                    <artifactId>mockito-core</artifactId>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
                     <groupId>org.slf4j</groupId>
                     <artifactId>slf4j-api</artifactId>
                 </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/6c5912f1/server/container/guice/guice-common/src/main/java/org/apache/james/utils/RetryExecutorUtil.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/RetryExecutorUtil.java
 
b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/RetryExecutorUtil.java
new file mode 100644
index 0000000..32b807e
--- /dev/null
+++ 
b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/RetryExecutorUtil.java
@@ -0,0 +1,38 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.utils;
+
+import com.nurkiewicz.asyncretry.AsyncRetryExecutor;
+
+public class RetryExecutorUtil {
+
+    public static final int INITIAL_DELAY_MILLIS = 500;
+    public static final int MULTIPLIER = 2;
+
+    public static AsyncRetryExecutor retryOnExceptions(AsyncRetryExecutor 
executor, int maxRetries, int minDelay, Class<? extends Throwable>... clazz) {
+        return executor
+            .retryOn(clazz)
+            .withExponentialBackoff(INITIAL_DELAY_MILLIS, MULTIPLIER)
+            .withProportionalJitter()
+            .withMaxRetries(maxRetries)
+            .withMinDelay(minDelay);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6c5912f1/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FaultyService.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FaultyService.java
 
b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FaultyService.java
new file mode 100644
index 0000000..12d8f92
--- /dev/null
+++ 
b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/FaultyService.java
@@ -0,0 +1,24 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.utils;
+
+public interface FaultyService {
+    String faultyService();
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6c5912f1/server/container/guice/guice-common/src/test/java/org/apache/james/utils/RetryExecutorUtilTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/guice-common/src/test/java/org/apache/james/utils/RetryExecutorUtilTest.java
 
b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/RetryExecutorUtilTest.java
new file mode 100644
index 0000000..32477ab
--- /dev/null
+++ 
b/server/container/guice/guice-common/src/test/java/org/apache/james/utils/RetryExecutorUtilTest.java
@@ -0,0 +1,124 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.utils;
+
+import com.nurkiewicz.asyncretry.AsyncRetryExecutor;
+import com.nurkiewicz.asyncretry.RetryExecutor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.BDDMockito.given;
+
+public class RetryExecutorUtilTest {
+    private static final int MAX_RETRIES = 3;
+    private static final int MIN_DELAY = 3000;
+    @Mock
+    protected FaultyService serviceMock;
+
+    private RetryExecutor retryExecutor;
+    private ScheduledExecutorService scheduledExecutor;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        scheduledExecutor.shutdownNow();
+    }
+
+    @Test
+    public void 
retryOnExceptionsAndExecuteShouldRethrowWhenScheduledServiceAlwaysThrowException()
 throws Exception {
+        given(serviceMock.faultyService())
+                .willThrow(IllegalArgumentException.class)
+                .willThrow(IllegalArgumentException.class)
+                .willThrow(IllegalArgumentException.class)
+                .willThrow(IllegalArgumentException.class);
+
+        retryExecutor = RetryExecutorUtil.retryOnExceptions(new 
AsyncRetryExecutor(scheduledExecutor), MAX_RETRIES, MIN_DELAY, 
IllegalArgumentException.class);
+
+        assertThatThrownBy(() -> 
retryExecutor.getWithRetry(serviceMock::faultyService).get())
+            .isInstanceOf(ExecutionException.class)
+            .hasCauseInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void 
retryOnExceptionsAndExecuteShouldRetryWhenMatchExceptionAndSuccess() throws 
Exception {
+        given(serviceMock.faultyService())
+                .willThrow(IllegalArgumentException.class)
+                .willReturn("Foo");
+        retryExecutor = RetryExecutorUtil.retryOnExceptions(new 
AsyncRetryExecutor(scheduledExecutor), MAX_RETRIES, MIN_DELAY, 
IllegalArgumentException.class);
+
+        final CompletableFuture<String> future = 
retryExecutor.getWithRetry(serviceMock::faultyService);
+
+        assertThat(future.get()).isEqualTo("Foo");
+    }
+
+    @Test
+    public void 
retryOnExceptionsAndExecuteShouldNotRetryWhenDoesNotMatchException() throws 
Exception {
+        given(serviceMock.faultyService())
+                .willThrow(IllegalStateException.class)
+                .willReturn("Foo");
+
+        retryExecutor = RetryExecutorUtil.retryOnExceptions(new 
AsyncRetryExecutor(scheduledExecutor), MAX_RETRIES, MIN_DELAY, 
IllegalArgumentException.class);
+
+        assertThatThrownBy(() -> 
retryExecutor.getWithRetry(serviceMock::faultyService).get())
+                .isInstanceOf(ExecutionException.class)
+                .hasCauseInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    public void 
retryOnExceptionsAndExecuteShouldRetryWithMaxTimesAndReturnValue() throws 
Exception {
+        given(serviceMock.faultyService())
+                .willThrow(IllegalStateException.class, 
IllegalStateException.class, IllegalStateException.class)
+                .willReturn("Foo");
+
+        retryExecutor = RetryExecutorUtil.retryOnExceptions(new 
AsyncRetryExecutor(scheduledExecutor), MAX_RETRIES, MIN_DELAY, 
IllegalStateException.class);
+
+        final CompletableFuture<String> future = 
retryExecutor.getWithRetry(serviceMock::faultyService);
+
+        assertThat(future.get()).isEqualTo("Foo");
+    }
+
+    @Test
+    public void retryOnExceptionsAndExecuteShouldFailIfFailMoreThanMaxRetry() 
throws Exception {
+        given(serviceMock.faultyService()).
+            willThrow(IllegalStateException.class, 
IllegalStateException.class, IllegalStateException.class, 
IllegalStateException.class).
+            willReturn("Foo");
+
+        retryExecutor = RetryExecutorUtil.retryOnExceptions(new 
AsyncRetryExecutor(scheduledExecutor), MAX_RETRIES, MIN_DELAY, 
IllegalStateException.class);
+
+        assertThatThrownBy(() -> 
retryExecutor.getWithRetry(serviceMock::faultyService).get())
+                .isInstanceOf(ExecutionException.class)
+                .hasCauseInstanceOf(IllegalStateException.class);
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to