Repository: clickhouse/clickhouse-java
Issue: NoHttpResponseException while intensive inserts

Hi!
I catch an error using sendStream in RowBinary format intensive queries(1M rows in batch every 3 second) One batch inserts in ~10-15 seconds. 
Clickhouse machine cpu usage is about 25%.
It appears after 5 minutes of job start.

I tried to catch problematic batch and insert in separately. Everything was fine.

clickouse-jdbc 0.2.4

 #https://github.com/ClickHouse/ClickHouse/issues/11766

Sample of usage
```
try (ClickHouseStatement statement = clickHouseDataSource.getConnection().createStatement()) {
                statement.write().send(QUERY_INSERT, batch, ClickHouseFormat.RowBinary);
```

Simple schema
```
CREATE TABLE IF NOT EXISTS t1
(
    timestamp   DateTime,
    sid         FixedString(10),
    url1        String,
    url2        String,
    importMonth UInt32 default toYYYYMM(now()),
    sidHash     UInt32 DEFAULT xxHash32(sid),
    url1Domain  String DEFAULT domainWithoutWWW(url1)
)
    ENGINE = MergeTree
        PARTITION BY (importMonth)
        ORDER BY (sidHash);
```
Timeouts config
```
clickHouseDataSource.getProperties().setSessionTimeout(600_000L);
        clickHouseDataSource.getProperties().setConnectionTimeout(600_000);
        clickHouseDataSource.getProperties().setSocketTimeout(600_000);
        clickHouseDataSource.getProperties().setDataTransferTimeout(600_000);
        clickHouseDataSource.getProperties().setKeepAliveTimeout(600_000);
```

Exception

```
Caused by: org.apache.http.NoHttpResponseException: server:8123 failed to respond
	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
	at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
	at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
	at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157)
	at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
	at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
	at ru.yandex.clickhouse.ClickHouseStatementImpl.sendStream(ClickHouseStatementImpl.java:849)
	... 13 common frames omitted
```

Error in clickhouse log 
```
2020.06.18 15:10:11.079888 [ 966 ] {c2912eff-d759-4b1b-80b3-151e5a96196a} <Error> executeQuery: Code: 23, e.displayText() = DB::Exception: Cannot read from istream at offset 22020096 (version 20.4.4.18 (official build)) (from server:53702) (in query: INSERT INTO tabl1(timestamp,sid,url1,url2) FORMAT RowBinary ), Stack trace (when copying this message, always include the lines below):

0. Poco::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0x104191d0 in /usr/bin/clickhouse
1. DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0x8fff8ad in /usr/bin/clickhouse
2. ? @ 0x90db204 in /usr/bin/clickhouse
3. DB::CompressedReadBufferBase::readCompressedData(unsigned long&, unsigned long&) @ 0xcdf7dce in /usr/bin/clickhouse
4. DB::CompressedReadBuffer::nextImpl() @ 0xcdf616b in /usr/bin/clickhouse
5. DB::ConcatReadBuffer::nextImpl() @ 0x90e8912 in /usr/bin/clickhouse
6. DB::ConcatReadBuffer::nextImpl() @ 0x90e8912 in /usr/bin/clickhouse
7. DB::ReadBuffer::readStrict(char*, unsigned long) @ 0x903b525 in /usr/bin/clickhouse
8. DB::DataTypeString::deserializeBinary(DB::IColumn&, DB::ReadBuffer&) const @ 0xcf3ade5 in /usr/bin/clickhouse
9. DB::BinaryRowInputFormat::readRow(std::__1::vector<COW<DB::IColumn>::mutable_ptr<DB::IColumn>, std::__1::allocator<COW<DB::IColumn>::mutable_ptr<DB::IColumn> > >&, DB::RowReadExtension&) @ 0xdb683af in /usr/bin/clickhouse
10. DB::IRowInputFormat::generate() @ 0xdb5d151 in /usr/bin/clickhouse
11. DB::ISource::work() @ 0xdaf3d8b in /usr/bin/clickhouse
12. DB::InputStreamFromInputFormat::readImpl() @ 0xdab99fd in /usr/bin/clickhouse
13. DB::IBlockInputStream::read() @ 0xce4825d in /usr/bin/clickhouse
14. DB::AddingDefaultsBlockInputStream::readImpl() @ 0xce3896b in /usr/bin/clickhouse
15. DB::IBlockInputStream::read() @ 0xce4825d in /usr/bin/clickhouse
16. DB::InputStreamFromASTInsertQuery::readImpl() @ 0xd1cbc39 in /usr/bin/clickhouse
17. DB::IBlockInputStream::read() @ 0xce4825d in /usr/bin/clickhouse
18. DB::copyData(DB::IBlockInputStream&, DB::IBlockOutputStream&, std::__1::atomic<bool>*) @ 0xce7717e in /usr/bin/clickhouse
19. DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, DB::Context&, std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)>) @ 0xd54d5ab in /usr/bin/clickhouse
20. DB::HTTPHandler::processQuery(Poco::Net::HTTPServerRequest&, HTMLForm&, Poco::Net::HTTPServerResponse&, DB::HTTPHandler::Output&) @ 0x90e47fc in /usr/bin/clickhouse
21. DB::HTTPHandler::handleRequest(Poco::Net::HTTPServerRequest&, Poco::Net::HTTPServerResponse&) @ 0x90e8256 in /usr/bin/clickhouse
22. Poco::Net::HTTPServerConnection::run() @ 0x102c9b83 in /usr/bin/clickhouse
23. Poco::Net::TCPServerConnection::start() @ 0x10304f4b in /usr/bin/clickhouse
24. Poco::Net::TCPServerDispatcher::run() @ 0x103053db in /usr/bin/clickhouse
25. Poco::PooledThread::run() @ 0x104b2fa6 in /usr/bin/clickhouse
26. Poco::ThreadImpl::runnableEntry(void*) @ 0x104ae260 in /usr/bin/clickhouse
27. start_thread @ 0x7fa3 in /lib/x86_64-linux-gnu/libpthread-2.28.so
28. __clone @ 0xf94cf in /lib/x86_64-linux-gnu/libc-2.28.so

2020.06.18 15:10:11.080144 [ 966 ] {} <Error> DynamicQueryHandler: Code: 23, e.displayText() = DB::Exception: Cannot read from istream at offset 22020096, Stack trace (when copying this message, always include the lines below):

0. Poco::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0x104191d0 in /usr/bin/clickhouse
1. DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0x8fff8ad in /usr/bin/clickhouse
2. ? @ 0x90db204 in /usr/bin/clickhouse
3. DB::CompressedReadBufferBase::readCompressedData(unsigned long&, unsigned long&) @ 0xcdf7dce in /usr/bin/clickhouse
4. DB::CompressedReadBuffer::nextImpl() @ 0xcdf616b in /usr/bin/clickhouse
5. DB::ConcatReadBuffer::nextImpl() @ 0x90e8912 in /usr/bin/clickhouse
6. DB::ConcatReadBuffer::nextImpl() @ 0x90e8912 in /usr/bin/clickhouse
7. DB::ReadBuffer::readStrict(char*, unsigned long) @ 0x903b525 in /usr/bin/clickhouse
8. DB::DataTypeString::deserializeBinary(DB::IColumn&, DB::ReadBuffer&) const @ 0xcf3ade5 in /usr/bin/clickhouse
9. DB::BinaryRowInputFormat::readRow(std::__1::vector<COW<DB::IColumn>::mutable_ptr<DB::IColumn>, std::__1::allocator<COW<DB::IColumn>::mutable_ptr<DB::IColumn> > >&, DB::RowReadExtension&) @ 0xdb683af in /usr/bin/clickhouse
10. DB::IRowInputFormat::generate() @ 0xdb5d151 in /usr/bin/clickhouse
11. DB::ISource::work() @ 0xdaf3d8b in /usr/bin/clickhouse
12. DB::InputStreamFromInputFormat::readImpl() @ 0xdab99fd in /usr/bin/clickhouse
13. DB::IBlockInputStream::read() @ 0xce4825d in /usr/bin/clickhouse
14. DB::AddingDefaultsBlockInputStream::readImpl() @ 0xce3896b in /usr/bin/clickhouse
15. DB::IBlockInputStream::read() @ 0xce4825d in /usr/bin/clickhouse
16. DB::InputStreamFromASTInsertQuery::readImpl() @ 0xd1cbc39 in /usr/bin/clickhouse
17. DB::IBlockInputStream::read() @ 0xce4825d in /usr/bin/clickhouse
18. DB::copyData(DB::IBlockInputStream&, DB::IBlockOutputStream&, std::__1::atomic<bool>*) @ 0xce7717e in /usr/bin/clickhouse
19. DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, DB::Context&, std::__1::function<void (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)>) @ 0xd54d5ab in /usr/bin/clickhouse
20. DB::HTTPHandler::processQuery(Poco::Net::HTTPServerRequest&, HTMLForm&, Poco::Net::HTTPServerResponse&, DB::HTTPHandler::Output&) @ 0x90e47fc in /usr/bin/clickhouse
21. DB::HTTPHandler::handleRequest(Poco::Net::HTTPServerRequest&, Poco::Net::HTTPServerResponse&) @ 0x90e8256 in /usr/bin/clickhouse
22. Poco::Net::HTTPServerConnection::run() @ 0x102c9b83 in /usr/bin/clickhouse
23. Poco::Net::TCPServerConnection::start() @ 0x10304f4b in /usr/bin/clickhouse
24. Poco::Net::TCPServerDispatcher::run() @ 0x103053db in /usr/bin/clickhouse
25. Poco::PooledThread::run() @ 0x104b2fa6 in /usr/bin/clickhouse
26. Poco::ThreadImpl::runnableEntry(void*) @ 0x104ae260 in /usr/bin/clickhouse
27. start_thread @ 0x7fa3 in /lib/x86_64-linux-gnu/libpthread-2.28.so
28. __clone @ 0xf94cf in /lib/x86_64-linux-gnu/libc-2.28.so
 (version 20.4.4.18 (official build))

```

Changed files:
src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java
src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java
src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java
src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java

diff --git a/src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java b/src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java
index 202574fe..6928a340 100644
--- a/src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java
+++ b/src/main/java/ru/yandex/clickhouse/settings/ClickHouseConnectionSettings.java
@@ -27,6 +27,7 @@ public enum ClickHouseConnectionSettings implements DriverPropertyCreator {
             + " ClickHouse rejects request execution if its time exceeds max_execution_time"),
 
 
+    @Deprecated
     KEEP_ALIVE_TIMEOUT("keepAliveTimeout", 30 * 1000, ""),
 
     /**
@@ -35,6 +36,7 @@ public enum ClickHouseConnectionSettings implements DriverPropertyCreator {
     TIME_TO_LIVE_MILLIS("timeToLiveMillis", 60 * 1000, ""),
     DEFAULT_MAX_PER_ROUTE("defaultMaxPerRoute", 500, ""),
     MAX_TOTAL("maxTotal", 10000, ""),
+    MAX_RETRIES("maxRetries", 3, "Maximum retries(default to 3) for idempotent operation. Set 0 to disable retry."),
 
     /**
      * additional
diff --git a/src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java b/src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java
index b368917e..6c01b194 100644
--- a/src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java
+++ b/src/main/java/ru/yandex/clickhouse/settings/ClickHouseProperties.java
@@ -22,6 +22,7 @@ public class ClickHouseProperties {
     private int timeToLiveMillis;
     private int defaultMaxPerRoute;
     private int maxTotal;
+    private int maxRetries;
     private String host;
     private int port;
     private boolean usePathAsDb;
@@ -113,6 +114,7 @@ public class ClickHouseProperties {
         this.timeToLiveMillis = (Integer)getSetting(info, ClickHouseConnectionSettings.TIME_TO_LIVE_MILLIS);
         this.defaultMaxPerRoute = (Integer)getSetting(info, ClickHouseConnectionSettings.DEFAULT_MAX_PER_ROUTE);
         this.maxTotal = (Integer)getSetting(info, ClickHouseConnectionSettings.MAX_TOTAL);
+        this.maxRetries = (Integer)getSetting(info, ClickHouseConnectionSettings.MAX_RETRIES);
         this.maxCompressBufferSize = (Integer) getSetting(info, ClickHouseConnectionSettings.MAX_COMPRESS_BUFFER_SIZE);
         this.ssl = (Boolean) getSetting(info, ClickHouseConnectionSettings.SSL);
         this.sslRootCertificate = (String) getSetting(info, ClickHouseConnectionSettings.SSL_ROOT_CERTIFICATE);
@@ -179,6 +181,7 @@ public class ClickHouseProperties {
         ret.put(ClickHouseConnectionSettings.TIME_TO_LIVE_MILLIS.getKey(), String.valueOf(timeToLiveMillis));
         ret.put(ClickHouseConnectionSettings.DEFAULT_MAX_PER_ROUTE.getKey(), String.valueOf(defaultMaxPerRoute));
         ret.put(ClickHouseConnectionSettings.MAX_TOTAL.getKey(), String.valueOf(maxTotal));
+        ret.put(ClickHouseConnectionSettings.MAX_RETRIES.getKey(), String.valueOf(maxRetries));
         ret.put(ClickHouseConnectionSettings.MAX_COMPRESS_BUFFER_SIZE.getKey(), String.valueOf(maxCompressBufferSize));
         ret.put(ClickHouseConnectionSettings.SSL.getKey(), String.valueOf(ssl));
         ret.put(ClickHouseConnectionSettings.SSL_ROOT_CERTIFICATE.getKey(), String.valueOf(sslRootCertificate));
@@ -248,6 +251,7 @@ public class ClickHouseProperties {
         setTimeToLiveMillis(properties.timeToLiveMillis);
         setDefaultMaxPerRoute(properties.defaultMaxPerRoute);
         setMaxTotal(properties.maxTotal);
+        setMaxRetries(properties.maxRetries);
         setMaxCompressBufferSize(properties.maxCompressBufferSize);
         setSsl(properties.ssl);
         setSslRootCertificate(properties.sslRootCertificate);
@@ -594,6 +598,14 @@ public class ClickHouseProperties {
         this.maxTotal = maxTotal;
     }
 
+    public int getMaxRetries() {
+        return maxRetries;
+    }
+
+    public void setMaxRetries(int maxRetries) {
+        this.maxRetries = maxRetries;
+    }
+
     public int getMaxCompressBufferSize() {
         return maxCompressBufferSize;
     }
diff --git a/src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java b/src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java
index 59e89314..66bc9980 100644
--- a/src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java
+++ b/src/main/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilder.java
@@ -27,20 +27,19 @@ import javax.net.ssl.TrustManagerFactory;
 
 import org.apache.http.ConnectionReuseStrategy;
 import org.apache.http.Header;
-import org.apache.http.HeaderElement;
-import org.apache.http.HeaderElementIterator;
 import org.apache.http.HttpHeaders;
 import org.apache.http.HttpHost;
 import org.apache.http.HttpResponse;
+import org.apache.http.NoHttpResponseException;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.AuthCache;
 import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.protocol.HttpClientContext;
 import org.apache.http.config.ConnectionConfig;
 import org.apache.http.config.RegistryBuilder;
-import org.apache.http.conn.ConnectionKeepAliveStrategy;
 import org.apache.http.conn.socket.ConnectionSocketFactory;
 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
 import org.apache.http.conn.ssl.NoopHostnameVerifier;
@@ -50,11 +49,10 @@ import org.apache.http.impl.auth.BasicScheme;
 import org.apache.http.impl.client.BasicAuthCache;
 import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
 import org.apache.http.message.BasicHeader;
-import org.apache.http.message.BasicHeaderElementIterator;
-import org.apache.http.protocol.HTTP;
 import org.apache.http.protocol.HttpContext;
 
 import ru.yandex.clickhouse.settings.ClickHouseProperties;
@@ -71,16 +69,32 @@ public class ClickHouseHttpClientBuilder {
     public CloseableHttpClient buildClient() throws Exception {
         return HttpClientBuilder.create()
                 .setConnectionManager(getConnectionManager())
+                .setRetryHandler(getRequestRetryHandler())
                 .setConnectionReuseStrategy(getConnectionReuseStrategy())
                 .setDefaultConnectionConfig(getConnectionConfig())
                 .setDefaultRequestConfig(getRequestConfig())
                 .setDefaultHeaders(getDefaultHeaders())
                 .setDefaultCredentialsProvider(getDefaultCredentialsProvider())
-                .disableContentCompression() // gzip здесь ни к чему. Используется lz4 при compress=1
+                .disableContentCompression() // gzip is not needed. Use lz4 when compress=1
                 .disableRedirectHandling()
                 .build();
     }
 
+    private HttpRequestRetryHandler getRequestRetryHandler() {
+        final int maxRetries = properties.getMaxRetries();
+        return new DefaultHttpRequestRetryHandler(maxRetries, false) {
+            @Override
+            public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
+                if (executionCount > maxRetries || context == null 
+                    || !Boolean.TRUE.equals(context.getAttribute("is_idempotent"))) {
+                    return false;
+                }
+
+                return (exception instanceof NoHttpResponseException) || super.retryRequest(exception, executionCount, context);
+            }
+        };
+    }
+
     public static HttpClientContext createClientContext(ClickHouseProperties props) {
         if (props == null
             || !isConfigurationValidForAuth(props))
@@ -155,29 +169,6 @@ public class ClickHouseHttpClientBuilder {
         return headers;
     }
 
-    private ConnectionKeepAliveStrategy createKeepAliveStrategy() {
-        return new ConnectionKeepAliveStrategy() {
-            @Override
-            public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) {
-                // in case of errors keep-alive not always works. close connection just in case
-                if (httpResponse.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
-                    return -1;
-                }
-                HeaderElementIterator it = new BasicHeaderElementIterator(
-                        httpResponse.headerIterator(HTTP.CONN_DIRECTIVE));
-                while (it.hasNext()) {
-                    HeaderElement he = it.nextElement();
-                    String param = he.getName();
-                    //String value = he.getValue();
-                    if (param != null && param.equalsIgnoreCase(HTTP.CONN_KEEP_ALIVE)) {
-                        return properties.getKeepAliveTimeout();
-                    }
-                }
-                return -1;
-            }
-        };
-    }
-
     private SSLContext getSSLContext()
       throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
       SSLContext ctx = SSLContext.getInstance("TLS");
diff --git a/src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java b/src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java
index e7cc8802..e7eee897 100644
--- a/src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java
+++ b/src/test/java/ru/yandex/clickhouse/util/ClickHouseHttpClientBuilderTest.java
@@ -1,8 +1,12 @@
 package ru.yandex.clickhouse.util;
 
 import org.apache.http.HttpHost;
+import org.apache.http.NoHttpResponseException;
 import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.HttpHostConnectException;
 import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
@@ -141,7 +145,72 @@ public class ClickHouseHttpClientBuilderTest {
                 null, null, "baz", "Basic ZGVmYXVsdDpiYXo=" // default:baz
             },
         };
+    }
+
+    private static WireMockServer newServer() {
+        WireMockServer server = new WireMockServer(
+            WireMockConfiguration.wireMockConfig().dynamicPort());
+        server.start();
+        server.stubFor(WireMock.post(WireMock.urlPathMatching("/*"))
+                .willReturn(WireMock.aResponse().withStatus(200).withHeader("Connection", "Keep-Alive")
+                        .withHeader("Content-Type", "text/plain; charset=UTF-8")
+                        .withHeader("Transfer-Encoding", "chunked").withHeader("Keep-Alive", "timeout=3")
+                        .withBody("OK.........................").withFixedDelay(2)));
+        return server;
+    }
 
+    private static void shutDownServerWithDelay(final WireMockServer server, final long delayMs) {
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(delayMs);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+
+                server.shutdownServer();
+                server.stop();
+            }
+        }.start();
     }
 
+    // @Test(dependsOnMethods = { "testWithRetry" }, expectedExceptions = { NoHttpResponseException.class })
+    public void testWithoutRetry() throws Exception {
+        final WireMockServer server = newServer();
+
+        ClickHouseProperties props = new ClickHouseProperties();
+        props.setMaxRetries(0);
+        ClickHouseHttpClientBuilder builder = new ClickHouseHttpClientBuilder(props);
+        CloseableHttpClient client = builder.buildClient();
+        HttpPost post = new HttpPost("http://localhost:" + server.port() + "/?db=system&query=select%201");
+
+        shutDownServerWithDelay(server, 100);
+
+        try {
+            client.execute(post);
+        } finally {
+            client.close();
+        }
+    }
+
+    // @Test(expectedExceptions = { HttpHostConnectException.class })
+    public void testWithRetry() throws Exception {
+        final WireMockServer server = newServer();
+
+        ClickHouseProperties props = new ClickHouseProperties();
+        // props.setMaxRetries(3);
+        ClickHouseHttpClientBuilder builder = new ClickHouseHttpClientBuilder(props);
+        CloseableHttpClient client = builder.buildClient();
+        HttpContext context = new BasicHttpContext();
+        context.setAttribute("is_idempotent", Boolean.TRUE);
+        HttpPost post = new HttpPost("http://localhost:" + server.port() + "/?db=system&query=select%202");
+        
+        shutDownServerWithDelay(server, 100);
+
+        try {
+            client.execute(post, context);
+        } finally {
+            client.close();
+        }
+    }
 }