You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ad...@apache.org on 2018/01/24 15:37:29 UTC
[ambari] 01/02: AMBARI-22805. Blueprints do not handle some
failures properly - improve error message in case of timeout
This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch branch-2.6
in repository https://gitbox.apache.org/repos/asf/ambari.git
commit c8921b6046aadc712ac4b389e825bc482129d40d
Author: Doroszlai, Attila <ad...@apache.org>
AuthorDate: Tue Jan 23 19:16:54 2018 +0100
AMBARI-22805. Blueprints do not handle some failures properly - improve error message in case of timeout
---
.../server/topology/AsyncCallableService.java | 12 ++++++++--
.../topology/tasks/ConfigureClusterTask.java | 5 +++--
.../server/topology/AsyncCallableServiceTest.java | 26 ++++++++++++++++++++++
3 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AsyncCallableService.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AsyncCallableService.java
index 3abb52c..1d8b322 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/AsyncCallableService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AsyncCallableService.java
@@ -81,8 +81,8 @@ public class AsyncCallableService<T> implements Callable<T> {
Future<T> future = executorService.submit(task);
LOG.info("Task {} execution started at {}", taskName, startTime);
+ Throwable lastError = null;
while (true) {
- Throwable lastError;
try {
LOG.debug("Task {} waiting for result at most {} ms", taskName, timeLeft);
T taskResult = future.get(timeLeft, TimeUnit.MILLISECONDS);
@@ -90,7 +90,9 @@ public class AsyncCallableService<T> implements Callable<T> {
return taskResult;
} catch (TimeoutException e) {
LOG.debug("Task {} timeout", taskName);
- lastError = e;
+ if (lastError == null) {
+ lastError = e;
+ }
timeLeft = 0;
} catch (ExecutionException e) {
Throwable cause = Throwables.getRootCause(e);
@@ -124,6 +126,12 @@ public class AsyncCallableService<T> implements Callable<T> {
public static class RetryTaskSilently extends RuntimeException {
// marker, throw if the task needs to be retried
+ public RetryTaskSilently() {
+ super();
+ }
+ public RetryTaskSilently(String message) {
+ super(message);
+ }
}
}
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/tasks/ConfigureClusterTask.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/tasks/ConfigureClusterTask.java
index 0f13ec2..ed1c451 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/tasks/ConfigureClusterTask.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/tasks/ConfigureClusterTask.java
@@ -71,8 +71,9 @@ public class ConfigureClusterTask implements Callable<Boolean> {
Collection<String> requiredHostGroups = getTopologyRequiredHostGroups();
if (!areHostGroupsResolved(requiredHostGroups)) {
- LOG.info("Some host groups require more hosts, cluster configuration cannot begin");
- throw new AsyncCallableService.RetryTaskSilently();
+ String msg = "Some host groups require more hosts, cluster configuration cannot begin";
+ LOG.info(msg);
+ throw new AsyncCallableService.RetryTaskSilently(msg);
}
LOG.info("All required host groups are complete, cluster configuration can now begin");
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/AsyncCallableServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/AsyncCallableServiceTest.java
index 3930e2e..bc8ef2b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/AsyncCallableServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/AsyncCallableServiceTest.java
@@ -18,10 +18,12 @@
package org.apache.ambari.server.topology;
+import static org.easymock.EasyMock.anyLong;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -82,6 +84,30 @@ public class AsyncCallableServiceTest extends EasyMockSupport {
}
@Test
+ public void lastErrorIsReturnedIfSubsequentAttemptTimesOut() throws Exception {
+ // GIVEN
+ Exception computationException = new ExecutionException(new ArithmeticException("Computation error during first attempt"));
+ Exception timeoutException = new TimeoutException("Timeout during second attempt");
+ expect(futureMock.get(TIMEOUT, TimeUnit.MILLISECONDS)).andThrow(computationException);
+ expect(executorServiceMock.schedule(taskMock, RETRY_DELAY, TimeUnit.MILLISECONDS)).andReturn(futureMock);
+ expect(futureMock.get(anyLong(), anyObject(TimeUnit.class))).andThrow(timeoutException);
+ expect(futureMock.isDone()).andReturn(Boolean.FALSE);
+ expect(futureMock.cancel(true)).andReturn(Boolean.TRUE);
+ expect(executorServiceMock.submit(taskMock)).andReturn(futureMock);
+ expect(onErrorMock.apply(computationException.getCause())).andReturn(null);
+ replayAll();
+
+ asyncCallableService = new AsyncCallableService<>(taskMock, TIMEOUT, RETRY_DELAY, "test", executorServiceMock, onErrorMock);
+
+ // WHEN
+ Boolean serviceResult = asyncCallableService.call();
+
+ // THEN
+ verifyAll();
+ Assert.assertNull("No result expected in case of timeout", serviceResult);
+ }
+
+ @Test
public void testCallableServiceShouldCancelTaskWhenTaskHangsAndTimeoutExceeded() throws Exception {
// GIVEN
//the task call hangs, it doesn't return within a reasonable period of time
--
To stop receiving notification emails like this one, please contact
adoroszlai@apache.org.