ClickHouseResponse handle(ClickHouseRequest<?> sealedRequest, Throwable cause) {
            // in case there's any recoverable exception wrapped by UncheckedIOException
            if (cause instanceof UncheckedIOException && cause.getCause() != null) {
                cause = ((UncheckedIOException) cause).getCause();
            }

            ClickHouseConfig config = sealedRequest.getConfig();
            log.debug("Handling %s(failover=%d, retry=%d)", cause, config.getFailover(), config.getRetry());
            ClickHouseException ex = ClickHouseException.of(cause, sealedRequest.getServer());
            try {
                if (config.isRepeatOnSessionLock()
                        && ex.getErrorCode() == ClickHouseException.ERROR_SESSION_IS_LOCKED) {
                    // connection timeout is usually a small number(defaults to 5000 ms), making it
                    // better default compare to socket timeout and max execution time etc.
                    return repeat(sealedRequest, ex, config.getSessionTimeout() <= 0 ? config.getConnectionTimeout()
                            : TimeUnit.SECONDS.toMillis(config.getSessionTimeout()));
                }

                int times = sealedRequest.getConfig().getFailover();
                if (times > 0) {
                    return failover(sealedRequest, ex, times);
                }

                // different from failover: 1) retry on the same node; 2) never retry on timeout
                times = sealedRequest.getConfig().getRetry();
                if (times > 0) {
                    return retry(sealedRequest, ex, times);
                }

                throw new CompletionException(cause);
            } catch (CompletionException e) {
                throw e;
            } catch (Exception e) {
                throw new CompletionException(e);
            }
        }
Repeats sending same request until success, timed out or running into a
different error.

@param sealedRequest non-null sealed request
@param exception     non-null exception to start with
@param timeout       timeout in milliseconds, zero or negative numbers means
                     no repeat
@return non-null response
@throws CompletionException when error occurred or timed out
clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClientBuilder.java