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
