Repository: calcite
Updated Branches:
  refs/heads/master db6a3b3b2 -> 799e1b083


[CALCITE-1315] Retry the request on NoHttpResponseException


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/799e1b08
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/799e1b08
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/799e1b08

Branch: refs/heads/master
Commit: 799e1b083b57d2295681d3e58c4d88563f7ccc91
Parents: db6a3b3
Author: Josh Elser <[email protected]>
Authored: Thu Jul 14 17:49:54 2016 -0400
Committer: Josh Elser <[email protected]>
Committed: Thu Jul 14 17:49:54 2016 -0400

----------------------------------------------------------------------
 .../remote/AvaticaCommonsHttpClientImpl.java    |  5 +++
 .../AvaticaCommonsHttpClientImplTest.java       | 36 ++++++++++++++++++++
 2 files changed, 41 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/799e1b08/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImpl.java
----------------------------------------------------------------------
diff --git 
a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImpl.java
 
b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImpl.java
index 8cd5340..5e8fb5f 100644
--- 
a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImpl.java
+++ 
b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImpl.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.avatica.remote;
 
 import org.apache.http.HttpHost;
+import org.apache.http.NoHttpResponseException;
 import org.apache.http.auth.AuthSchemeProvider;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
@@ -142,6 +143,10 @@ public class AvaticaCommonsHttpClientImpl implements 
AvaticaHttpClient,
         }
 
         throw new RuntimeException("Failed to execute HTTP Request, got HTTP/" 
+ statusCode);
+      } catch (NoHttpResponseException e) {
+        // This can happen when sitting behind a load balancer and a backend 
server dies
+        LOG.debug("The server failed to issue an HTTP response, retrying");
+        continue;
       } catch (RuntimeException e) {
         throw e;
       } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/799e1b08/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImplTest.java
----------------------------------------------------------------------
diff --git 
a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImplTest.java
 
b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImplTest.java
index b7c49a3..990ecd2 100644
--- 
a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImplTest.java
+++ 
b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/AvaticaCommonsHttpClientImplTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.calcite.avatica.remote;
 
+import org.apache.http.NoHttpResponseException;
 import org.apache.http.StatusLine;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpPost;
@@ -74,6 +75,41 @@ public class AvaticaCommonsHttpClientImplTest {
     byte[] responseBytes = client.send(requestBytes);
     assertEquals("success", new String(responseBytes, UTF_8));
   }
+
+  @Test public void testRetryOnMissingHttpResponse() throws Exception {
+    final byte[] requestBytes = "fake_request".getBytes(UTF_8);
+    final CloseableHttpResponse badResponse = 
mock(CloseableHttpResponse.class);
+    final CloseableHttpResponse goodResponse = 
mock(CloseableHttpResponse.class);
+    final StatusLine badStatusLine = mock(StatusLine.class);
+    final StatusLine goodStatusLine = mock(StatusLine.class);
+    final StringEntity responseEntity = new StringEntity("success");
+    final Answer<CloseableHttpResponse> failThenSucceed = new 
Answer<CloseableHttpResponse>() {
+      private int iteration = 0;
+      @Override public CloseableHttpResponse answer(InvocationOnMock 
invocation) throws Throwable {
+        iteration++;
+        if (1 == iteration) {
+          throw new NoHttpResponseException("The server didn't respond!");
+        } else {
+          return goodResponse;
+        }
+      }
+    };
+
+    final AvaticaCommonsHttpClientImpl client = 
mock(AvaticaCommonsHttpClientImpl.class);
+
+    when(client.send(any(byte[].class))).thenCallRealMethod();
+    when(client.execute(any(HttpPost.class), 
any(HttpClientContext.class))).then(failThenSucceed);
+
+    when(badResponse.getStatusLine()).thenReturn(badStatusLine);
+    
when(badStatusLine.getStatusCode()).thenReturn(HttpURLConnection.HTTP_UNAVAILABLE);
+
+    when(goodResponse.getStatusLine()).thenReturn(goodStatusLine);
+    when(goodStatusLine.getStatusCode()).thenReturn(HttpURLConnection.HTTP_OK);
+    when(goodResponse.getEntity()).thenReturn(responseEntity);
+
+    byte[] responseBytes = client.send(requestBytes);
+    assertEquals("success", new String(responseBytes, UTF_8));
+  }
 }
 
 // End AvaticaCommonsHttpClientImplTest.java

Reply via email to