-
Notifications
You must be signed in to change notification settings - Fork 614
Polish excpetion api + build in code list that is retryable #2453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6425c9b
87a4af6
cf0887e
c0692bc
64964bd
ba72853
2fde678
d7dac9e
88cab89
b3986f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.clickhouse.client.api; | ||
|
|
||
| public class ClickHouseException extends RuntimeException { | ||
| protected boolean isRetryable = false; | ||
|
|
||
| public ClickHouseException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public ClickHouseException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
|
|
||
| public ClickHouseException(Throwable cause) { | ||
| super(cause); | ||
| } | ||
| public boolean isRetryable() { return isRetryable; } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -813,7 +813,7 @@ public Builder setClientNetworkBufferSize(int size) { | |||||
|
|
||||||
| /** | ||||||
| * Sets list of causes that should be retried on. | ||||||
| * Default {@code [NoHttpResponse, ConnectTimeout, ConnectionRequestTimeout]} | ||||||
| * Default {@code [NoHttpResponse, ConnectTimeout, ConnectionRequestTimeout, ServerRetryable]} | ||||||
| * Use {@link ClientFaultCause#None} to disable retries. | ||||||
| * | ||||||
| * @param causes - list of causes | ||||||
|
|
@@ -1464,7 +1464,8 @@ public CompletableFuture<InsertResponse> insert(String tableName, | |||||
| } | ||||||
| } | ||||||
| } | ||||||
| throw new ClientException("Insert request failed after attempts: " + (retries + 1) + " - Duration: " + (System.nanoTime() - startTime), lastException); | ||||||
| LOG.warn("Insert request failed after attempts: " + (retries + 1) + " - Duration: " + (System.nanoTime() - startTime)); | ||||||
| throw lastException; | ||||||
| }; | ||||||
|
|
||||||
| return runAsyncOperation(responseSupplier, settings.getAllSettings()); | ||||||
|
|
@@ -1586,8 +1587,8 @@ public CompletableFuture<QueryResponse> query(String sqlQuery, Map<String, Objec | |||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| throw new ClientException("Query request failed after attempts: " + (retries + 1) + " - Duration: " + (System.nanoTime() - startTime), lastException); | ||||||
| LOG.warn("Query request failed after attempts: " + (retries + 1) + " - Duration: " + (System.nanoTime() - startTime)); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The warning log is missing the exception object parameter. Consider adding the
Suggested change
|
||||||
| throw lastException; | ||||||
| }; | ||||||
|
|
||||||
| return runAsyncOperation(responseSupplier, settings.getAllSettings()); | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,12 @@ | ||
| package com.clickhouse.client.api; | ||
| public class ClientException extends RuntimeException { | ||
| public ClientException(String message) { | ||
| super(message); | ||
| } | ||
| public ClientException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
| package com.clickhouse.client.api; | ||
|
|
||
| public class ClientException extends ClickHouseException { | ||
|
|
||
| public ClientException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public ClientException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,14 @@ | ||
| package com.clickhouse.client.api; | ||
|
|
||
| public class ConnectionInitiationException extends ClientException { | ||
|
|
||
| public ConnectionInitiationException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public ConnectionInitiationException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
| package com.clickhouse.client.api; | ||
|
|
||
| public class ConnectionInitiationException extends ClickHouseException { | ||
|
|
||
| public ConnectionInitiationException(String message) { | ||
| super(message); | ||
| this.isRetryable = true; | ||
| } | ||
|
|
||
| public ConnectionInitiationException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| this.isRetryable = true; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.clickhouse.client.api; | ||
|
|
||
| public class DataTransferException extends ClickHouseException { | ||
|
|
||
| public DataTransferException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public DataTransferException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,40 +1,69 @@ | ||
| package com.clickhouse.client.api; | ||
|
|
||
| public class ServerException extends RuntimeException { | ||
|
|
||
| public static final int CODE_UNKNOWN = 0; | ||
|
|
||
| public static final int TABLE_NOT_FOUND = 60; | ||
|
|
||
| private final int code; | ||
|
|
||
| private final int transportProtocolCode; | ||
|
|
||
| public ServerException(int code, String message) { | ||
| this(code, message, 500); | ||
| } | ||
|
|
||
| public ServerException(int code, String message, int transportProtocolCode) { | ||
| super(message); | ||
| this.code = code; | ||
| this.transportProtocolCode = transportProtocolCode; | ||
| } | ||
|
|
||
| /** | ||
| * Returns CH server error code. May return 0 if code is unknown. | ||
| * @return - error code from server response | ||
| */ | ||
| public int getCode() { | ||
| return code; | ||
| } | ||
|
|
||
| /** | ||
| * Returns error code of underlying transport protocol. For example, HTTP status. | ||
| * By default, will return {@code 500 } what is derived from HTTP Server Internal Error. | ||
| * | ||
| * @return - transport status code | ||
| */ | ||
| public int getTransportProtocolCode() { | ||
| return transportProtocolCode; | ||
| } | ||
| } | ||
| package com.clickhouse.client.api; | ||
|
|
||
| public class ServerException extends ClickHouseException { | ||
|
|
||
| public static final int CODE_UNKNOWN = 0; | ||
|
|
||
| public static final int TABLE_NOT_FOUND = 60; | ||
|
|
||
| private final int code; | ||
|
|
||
| private final int transportProtocolCode; | ||
|
|
||
| public ServerException(int code, String message) { | ||
| this(code, message, 500); | ||
| } | ||
|
|
||
| public ServerException(int code, String message, int transportProtocolCode) { | ||
| super(message); | ||
| this.code = code; | ||
| this.transportProtocolCode = transportProtocolCode; | ||
| this.isRetryable = discoverIsRetryable(code, message, transportProtocolCode); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code references |
||
| } | ||
|
|
||
| /** | ||
| * Returns CH server error code. May return 0 if code is unknown. | ||
| * @return - error code from server response | ||
| */ | ||
| public int getCode() { | ||
| return code; | ||
| } | ||
|
|
||
| /** | ||
| * Returns error code of underlying transport protocol. For example, HTTP status. | ||
| * By default, will return {@code 500 } what is derived from HTTP Server Internal Error. | ||
| * | ||
| * @return - transport status code | ||
| */ | ||
| public int getTransportProtocolCode() { | ||
| return transportProtocolCode; | ||
| } | ||
|
|
||
| public boolean isRetryable() { | ||
| return isRetryable; | ||
| } | ||
|
|
||
| private boolean discoverIsRetryable(int code, String message, int transportProtocolCode) { | ||
| //Let's check if we have a ServerException to reference the error code | ||
| //https://github.com/ClickHouse/ClickHouse/blob/master/src/Common/ErrorCodes.cpp | ||
| switch (code) { // UNEXPECTED_END_OF_FILE | ||
| case 3: // UNEXPECTED_END_OF_FILE | ||
| case 107: // FILE_DOESNT_EXIST | ||
| case 159: // TIMEOUT_EXCEEDED | ||
| case 164: // READONLY | ||
| case 202: // TOO_MANY_SIMULTANEOUS_QUERIES | ||
| case 203: // NO_FREE_CONNECTION | ||
| case 209: // SOCKET_TIMEOUT | ||
| case 210: // NETWORK_ERROR | ||
| case 241: // MEMORY_LIMIT_EXCEEDED | ||
| case 242: // TABLE_IS_READ_ONLY | ||
| case 252: // TOO_MANY_PARTS | ||
| case 285: // TOO_FEW_LIVE_REPLICAS | ||
| case 319: // UNKNOWN_STATUS_OF_INSERT | ||
| case 425: // SYSTEM_ERROR | ||
| case 999: // KEEPER_EXCEPTION | ||
| return true; | ||
| }; | ||
| return false; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,7 @@ | ||
| package com.clickhouse.client.api.internal; | ||
|
|
||
| import com.clickhouse.client.ClickHouseSslContextProvider; | ||
| import com.clickhouse.client.api.Client; | ||
| import com.clickhouse.client.api.ClientConfigProperties; | ||
| import com.clickhouse.client.api.ClientException; | ||
| import com.clickhouse.client.api.ClientFaultCause; | ||
| import com.clickhouse.client.api.ClientMisconfigurationException; | ||
| import com.clickhouse.client.api.ConnectionInitiationException; | ||
| import com.clickhouse.client.api.ConnectionReuseStrategy; | ||
| import com.clickhouse.client.api.ServerException; | ||
| import com.clickhouse.client.api.*; | ||
| import com.clickhouse.client.api.data_formats.internal.SerializerUtils; | ||
| import com.clickhouse.client.api.enums.ProxyType; | ||
| import com.clickhouse.client.api.http.ClickHouseHttpProto; | ||
|
|
@@ -379,7 +372,7 @@ public Exception readError(ClassicHttpResponse httpResponse) { | |
| private AtomicLong timeToPoolVent = new AtomicLong(0); | ||
|
|
||
| public ClassicHttpResponse executeRequest(Endpoint server, Map<String, Object> requestConfig, LZ4Factory lz4Factory, | ||
| IOCallback<OutputStream> writeCallback) throws IOException { | ||
| IOCallback<OutputStream> writeCallback) throws Exception { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method signature has been changed from throwing |
||
| if (poolControl != null && timeToPoolVent.get() < System.currentTimeMillis()) { | ||
| timeToPoolVent.set(System.currentTimeMillis() + POOL_VENT_TIMEOUT); | ||
| poolControl.closeExpired(); | ||
|
|
@@ -432,14 +425,10 @@ public ClassicHttpResponse executeRequest(Endpoint server, Map<String, Object> r | |
|
|
||
| } catch (UnknownHostException e) { | ||
| LOG.warn("Host '{}' unknown", server.getBaseURL()); | ||
| throw new ClientException("Unknown host", e); | ||
| throw e; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change removes the wrapping of |
||
| } catch (ConnectException | NoRouteToHostException e) { | ||
| LOG.warn("Failed to connect to '{}': {}", server.getBaseURL(), e.getMessage()); | ||
| throw new ClientException("Failed to connect", e); | ||
| } catch (ConnectionRequestTimeoutException | ServerException | NoHttpResponseException | ClientException | SocketTimeoutException e) { | ||
| throw e; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change removes the wrapping of |
||
| } catch (Exception e) { | ||
| throw new ClientException(e.getMessage(), e); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -651,6 +640,12 @@ public boolean shouldRetry(Throwable ex, Map<String, Object> requestSettings) { | |
| return retryCauses.contains(ClientFaultCause.SocketTimeout); | ||
| } | ||
|
|
||
| // there are some db retryable error codes | ||
| if (ex instanceof ServerException || ex.getCause() instanceof ServerException) { | ||
| ServerException se = (ServerException) ex; | ||
| return se.isRetryable() && retryCauses.contains(ClientFaultCause.ServerRetryable); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
|
|
@@ -664,11 +659,17 @@ public RuntimeException wrapException(String message, Exception cause) { | |
| if (cause instanceof ConnectionRequestTimeoutException || | ||
| cause instanceof NoHttpResponseException || | ||
| cause instanceof ConnectTimeoutException || | ||
| cause instanceof ConnectException) { | ||
| cause instanceof ConnectException || | ||
| cause instanceof UnknownHostException || | ||
| cause instanceof NoRouteToHostException) { | ||
| return new ConnectionInitiationException(message, cause); | ||
| } | ||
|
|
||
| return new ClientException(message, cause); | ||
| if (cause instanceof SocketTimeoutException || cause instanceof IOException) { | ||
| return new DataTransferException(message, cause); | ||
| } | ||
| // if we can not identify the exception explicitly we catch as our base exception ClickHouseException | ||
| return new ClickHouseException(message, cause); | ||
| } | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning log is missing the exception object parameter. Consider adding the
lastExceptionas the last parameter to theLOG.warn()call to include the stack trace in logs: