Skip to content

Commit 4ea6dc5

Browse files
committed
Add getProgramFailureExceptionByGrpcStatusCode
1 parent 3473bbe commit 4ea6dc5

File tree

4 files changed

+87
-97
lines changed

4 files changed

+87
-97
lines changed

src/main/java/io/cdap/plugin/gcp/bigtable/common/BigtableErrorDetailsProvider.java

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,23 @@
1616

1717
package io.cdap.plugin.gcp.bigtable.common;
1818

19-
import com.google.bigtable.repackaged.io.grpc.Status;
2019
import com.google.bigtable.repackaged.io.grpc.StatusRuntimeException;
2120
import com.google.common.base.Throwables;
22-
import io.cdap.cdap.api.exception.ErrorCategory;
23-
import io.cdap.cdap.api.exception.ErrorCodeType;
24-
import io.cdap.cdap.api.exception.ErrorType;
25-
import io.cdap.cdap.api.exception.ErrorUtils;
2621
import io.cdap.cdap.api.exception.ProgramFailureException;
2722
import io.cdap.cdap.etl.api.exception.ErrorContext;
2823
import io.cdap.plugin.gcp.common.GCPErrorDetailsProvider;
24+
import io.cdap.plugin.gcp.common.GCPErrorDetailsProviderUtil;
2925
import io.cdap.plugin.gcp.common.GCPUtils;
3026

3127
import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
3228

33-
import java.util.HashMap;
3429
import java.util.List;
35-
import java.util.Map;
3630

3731

3832
/**
3933
* A custom ErrorDetailsProvider for BigTable plugins.
4034
*/
4135
public class BigtableErrorDetailsProvider extends GCPErrorDetailsProvider {
42-
private static final String ERROR_MESSAGE_FORMAT = "Error occurred in the phase: '%s'. Error message: %s";
43-
44-
static Map<Status.Code, Integer> actionErrorMap = new HashMap<>();
45-
46-
static {
47-
actionErrorMap.put(Status.Code.CANCELLED, 499);
48-
actionErrorMap.put(Status.Code.UNKNOWN, 500);
49-
actionErrorMap.put(Status.Code.INVALID_ARGUMENT, 400);
50-
actionErrorMap.put(Status.Code.DEADLINE_EXCEEDED, 504);
51-
actionErrorMap.put(Status.Code.NOT_FOUND, 404);
52-
actionErrorMap.put(Status.Code.ALREADY_EXISTS, 409);
53-
actionErrorMap.put(Status.Code.PERMISSION_DENIED, 403);
54-
actionErrorMap.put(Status.Code.UNAUTHENTICATED, 401);
55-
actionErrorMap.put(Status.Code.RESOURCE_EXHAUSTED, 429);
56-
actionErrorMap.put(Status.Code.FAILED_PRECONDITION, 400);
57-
actionErrorMap.put(Status.Code.ABORTED, 409);
58-
actionErrorMap.put(Status.Code.OUT_OF_RANGE, 400);
59-
actionErrorMap.put(Status.Code.UNIMPLEMENTED, 501);
60-
actionErrorMap.put(Status.Code.INTERNAL, 500);
61-
actionErrorMap.put(Status.Code.UNAVAILABLE, 503);
62-
actionErrorMap.put(Status.Code.DATA_LOSS, 500);
63-
}
6436

6537
@Override
6638
protected String getExternalDocumentationLink() {
@@ -83,8 +55,8 @@ public ProgramFailureException getExceptionDetails(Exception e, ErrorContext err
8355
RetriesExhaustedWithDetailsException r = (RetriesExhaustedWithDetailsException) t;
8456
List<Throwable> innerCauses = r.getCauses();
8557
for (Throwable innerCause : innerCauses) {
86-
if (innerCause instanceof StatusRuntimeException) {
87-
return getProgramFailureExceptionFromBigTableException((StatusRuntimeException) innerCause);
58+
if (innerCause instanceof Exception) {
59+
return this.getExceptionDetails((Exception) innerCause, errorContext);
8860
}
8961
}
9062
}
@@ -93,23 +65,7 @@ public ProgramFailureException getExceptionDetails(Exception e, ErrorContext err
9365
}
9466

9567
private ProgramFailureException getProgramFailureExceptionFromBigTableException(StatusRuntimeException se) {
96-
int httpStatusCode = actionErrorMap.get(se.getStatus().getCode());
97-
ErrorUtils.ActionErrorPair actionErrorPair = null;
98-
String errorReason = se.getMessage();
99-
String errorMessage = se.getMessage();
100-
if (actionErrorMap.containsKey(se.getStatus().getCode())) {
101-
actionErrorPair = ErrorUtils.getActionErrorByStatusCode(httpStatusCode);
102-
errorReason = String.format("%s %s. %s", httpStatusCode, errorMessage, actionErrorPair.getCorrectiveAction());
103-
}
104-
if (!errorReason.endsWith(".")) {
105-
errorReason = errorReason + ".";
106-
}
107-
errorReason = String.format("%s For more details, see %s.", errorReason, GCPUtils.BIG_TABLE_SUPPORTED_DOC_URL);
108-
109-
String errorMessageWithCode = String.format("[ErrorCode='%s'] %s", httpStatusCode, errorMessage);
110-
return ErrorUtils.getProgramFailureException(new ErrorCategory(ErrorCategory.ErrorCategoryEnum.PLUGIN),
111-
errorReason, String.format("%s: %s", se.getClass().getName(), errorMessageWithCode),
112-
actionErrorPair != null ? actionErrorPair.getErrorType() : ErrorType.UNKNOWN, true, ErrorCodeType.HTTP,
113-
String.valueOf(httpStatusCode), GCPUtils.SPANNER_SUPPORTED_DOC_URL, se);
68+
return GCPErrorDetailsProviderUtil.getProgramFailureExceptionByGrpcStatusCode(se.getStatus().getCode().value(),
69+
se.getMessage(), se.getMessage(), GCPUtils.BIG_TABLE_SUPPORTED_DOC_URL, se);
11470
}
11571
}

src/main/java/io/cdap/plugin/gcp/common/GCPErrorDetailsProviderUtil.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,57 @@
3030
import io.cdap.cdap.etl.api.exception.ErrorContext;
3131

3232
import java.io.IOException;
33+
import java.util.HashMap;
3334
import java.util.List;
35+
import java.util.Map;
3436
import javax.annotation.Nullable;
3537

3638
/**
3739
* Common functions for GCP error details provider related functionalities.
3840
*/
3941
public final class GCPErrorDetailsProviderUtil {
4042

43+
public static final Map<Integer, Integer> GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP = new HashMap<>();
44+
45+
static {
46+
// https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
47+
// OK 0 <--> HTTP 200 (OK)
48+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(0, 200);
49+
// CANCELLED 1 <--> HTTP 499 (Client Closed Request)
50+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(1, 499);
51+
// UNKNOWN 2 <--> HTTP 500 (Internal Server Error)
52+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(2, 500);
53+
// INVALID_ARGUMENT 3 <--> HTTP 400 (Bad Request)
54+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(3, 400);
55+
// DEADLINE_EXCEEDED 4 <--> HTTP 504 (Gateway Timeout)
56+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(4, 504);
57+
// NOT_FOUND 5 <--> HTTP 404 (Not Found)
58+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(5, 404);
59+
// ALREADY_EXISTS 6 <--> HTTP 409 (Conflict)
60+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(6, 409);
61+
// PERMISSION_DENIED 7 <--> HTTP 403 (Forbidden)
62+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(7, 403);
63+
// RESOURCE_EXHAUSTED 8 <--> HTTP 429 (Too Many Requests)
64+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(8, 429);
65+
// FAILED_PRECONDITION 9 <--> HTTP 400 (Bad Request)
66+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(9, 400);
67+
// ABORTED 10 <--> HTTP 409 (Conflict)
68+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(10, 409);
69+
// OUT_OF_RANGE 11 <--> HTTP 400 (Bad Request)
70+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(11, 400);
71+
// UNIMPLEMENTED 12 <--> HTTP 501 (Not Implemented)
72+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(12, 501);
73+
// INTERNAL 13 <--> HTTP 500 (Internal Server Error)
74+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(13, 500);
75+
// UNAVAILABLE 14 <--> HTTP 503 (Service Unavailable)
76+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(14, 503);
77+
// DATA_LOSS 15 <--> HTTP 500 (Internal Server Error)
78+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(15, 500);
79+
// UNAUTHENTICATED 16 <--> HTTP 401 (Unauthorized)
80+
GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.put(16, 401);
81+
}
82+
83+
4184
/**
4285
* Get a ProgramFailureException with the given error
4386
* information from {@link HttpResponseException}.
@@ -130,4 +173,39 @@ private static String getErrorMessage(GoogleJsonResponseException exception) {
130173
}
131174
return exception.getMessage();
132175
}
176+
177+
178+
/**
179+
* Get the HTTP status code for a given gRPC error code.
180+
*
181+
* @param grpcStatusCode the int value of the gRPC error code
182+
*/
183+
public static ErrorUtils.ActionErrorPair getActionErrorByGrpcStatusCode(int grpcStatusCode) {
184+
if (!GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.containsKey(grpcStatusCode)) {
185+
return null;
186+
}
187+
return ErrorUtils.getActionErrorByStatusCode(GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.get(grpcStatusCode));
188+
}
189+
190+
public static ProgramFailureException getProgramFailureExceptionByGrpcStatusCode(int grpcErrorCodeValue,
191+
String grpcErrorReason, String grpcErrorMessage, String supportedDocUrl, Exception se) {
192+
int httpStatusCode = GCPErrorDetailsProviderUtil.GCP_GRPC_ERROR_CODE_HTTP_STATUS_CODE_MAP.get(grpcErrorCodeValue);
193+
ErrorUtils.ActionErrorPair actionErrorPair = GCPErrorDetailsProviderUtil.getActionErrorByGrpcStatusCode(
194+
grpcErrorCodeValue);
195+
String errorReason = grpcErrorReason;
196+
if (actionErrorPair != null) {
197+
errorReason = String.format("%s %s. %s", httpStatusCode, grpcErrorMessage, actionErrorPair.getCorrectiveAction());
198+
}
199+
if (!errorReason.endsWith(".")) {
200+
errorReason = errorReason + ".";
201+
}
202+
errorReason = String.format("%s For more details, see %s.", errorReason, supportedDocUrl);
203+
204+
String errorMessageWithCode = String.format("[ErrorCode='%s'] %s", httpStatusCode, grpcErrorMessage);
205+
return ErrorUtils.getProgramFailureException(new ErrorCategory(ErrorCategory.ErrorCategoryEnum.PLUGIN), errorReason,
206+
String.format("%s: %s", se.getClass().getName(), errorMessageWithCode),
207+
actionErrorPair != null ? actionErrorPair.getErrorType() : ErrorType.UNKNOWN, true, ErrorCodeType.HTTP,
208+
String.valueOf(httpStatusCode), supportedDocUrl, se);
209+
}
210+
133211
}

src/main/java/io/cdap/plugin/gcp/common/GCPUtils.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import com.google.cloud.storage.StorageException;
3636
import com.google.cloud.storage.StorageOptions;
3737
import com.google.gson.reflect.TypeToken;
38-
import io.cdap.plugin.gcp.bigquery.util.BigQueryUtil;
3938
import io.cdap.plugin.gcp.gcs.GCSPath;
4039
import io.cdap.plugin.gcp.gcs.ServiceAccountAccessTokenProvider;
4140
import org.apache.hadoop.conf.Configuration;

src/main/java/io/cdap/plugin/gcp/spanner/common/SpannerErrorDetailsProvider.java

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,19 @@
1616

1717
package io.cdap.plugin.gcp.spanner.common;
1818

19-
import com.google.cloud.spanner.ErrorCode;
2019
import com.google.cloud.spanner.SpannerException;
2120
import com.google.common.base.Throwables;
22-
import io.cdap.cdap.api.exception.ErrorCategory;
23-
import io.cdap.cdap.api.exception.ErrorCodeType;
24-
import io.cdap.cdap.api.exception.ErrorType;
25-
import io.cdap.cdap.api.exception.ErrorUtils;
2621
import io.cdap.cdap.api.exception.ProgramFailureException;
2722
import io.cdap.cdap.etl.api.exception.ErrorContext;
2823
import io.cdap.plugin.gcp.common.GCPErrorDetailsProvider;
24+
import io.cdap.plugin.gcp.common.GCPErrorDetailsProviderUtil;
2925
import io.cdap.plugin.gcp.common.GCPUtils;
30-
import java.util.HashMap;
3126
import java.util.List;
32-
import java.util.Map;
3327

3428
/**
3529
* A custom ErrorDetailsProvider for Spanner.
3630
*/
3731
public class SpannerErrorDetailsProvider extends GCPErrorDetailsProvider {
38-
private static final String ERROR_MESSAGE_FORMAT = "Error occurred in the phase: '%s'. Error message: %s";
39-
40-
static Map<ErrorCode, Integer> actionErrorMap = new HashMap<>();
41-
42-
static {
43-
actionErrorMap.put(ErrorCode.CANCELLED, 499);
44-
actionErrorMap.put(ErrorCode.UNKNOWN, 500);
45-
actionErrorMap.put(ErrorCode.INVALID_ARGUMENT, 400);
46-
actionErrorMap.put(ErrorCode.DEADLINE_EXCEEDED, 504);
47-
actionErrorMap.put(ErrorCode.NOT_FOUND, 404);
48-
actionErrorMap.put(ErrorCode.ALREADY_EXISTS, 409);
49-
actionErrorMap.put(ErrorCode.PERMISSION_DENIED, 403);
50-
actionErrorMap.put(ErrorCode.UNAUTHENTICATED, 401);
51-
actionErrorMap.put(ErrorCode.RESOURCE_EXHAUSTED, 429);
52-
actionErrorMap.put(ErrorCode.FAILED_PRECONDITION, 400);
53-
actionErrorMap.put(ErrorCode.ABORTED, 409);
54-
actionErrorMap.put(ErrorCode.OUT_OF_RANGE, 400);
55-
actionErrorMap.put(ErrorCode.UNIMPLEMENTED, 501);
56-
actionErrorMap.put(ErrorCode.INTERNAL, 500);
57-
actionErrorMap.put(ErrorCode.UNAVAILABLE, 503);
58-
actionErrorMap.put(ErrorCode.DATA_LOSS, 500);
59-
}
6032

6133
@Override
6234
protected String getExternalDocumentationLink() {
@@ -79,23 +51,8 @@ public ProgramFailureException getExceptionDetails(Exception e, ErrorContext err
7951
}
8052

8153
private ProgramFailureException getProgramFailureExceptionFromSpannerException(SpannerException se) {
82-
int httpStatusCode = actionErrorMap.get(se.getErrorCode());
83-
ErrorUtils.ActionErrorPair actionErrorPair = null;
84-
String errorReason = se.getReason();
85-
String errorMessage = se.getMessage();
86-
if (actionErrorMap.containsKey(se.getErrorCode())) {
87-
actionErrorPair = ErrorUtils.getActionErrorByStatusCode(httpStatusCode);
88-
errorReason = String.format("%s %s. %s", httpStatusCode, errorMessage, actionErrorPair.getCorrectiveAction());
89-
}
90-
if (!errorReason.endsWith(".")) {
91-
errorReason = errorReason + ".";
92-
}
93-
errorReason = String.format("%s For more details, see %s.", errorReason, GCPUtils.SPANNER_SUPPORTED_DOC_URL);
94-
95-
String errorMessageWithCode = String.format("[ErrorCode='%s'] %s", httpStatusCode, errorMessage);
96-
return ErrorUtils.getProgramFailureException(new ErrorCategory(ErrorCategory.ErrorCategoryEnum.PLUGIN),
97-
errorReason, String.format("%s: %s", se.getClass().getName(), errorMessageWithCode),
98-
actionErrorPair != null ? actionErrorPair.getErrorType() : ErrorType.UNKNOWN, true, ErrorCodeType.HTTP,
99-
String.valueOf(httpStatusCode), GCPUtils.SPANNER_SUPPORTED_DOC_URL, se);
54+
return GCPErrorDetailsProviderUtil.getProgramFailureExceptionByGrpcStatusCode(
55+
se.getErrorCode().getGrpcStatusCode().value(), se.getReason(), se.getMessage(),
56+
GCPUtils.SPANNER_SUPPORTED_DOC_URL, se);
10057
}
10158
}

0 commit comments

Comments
 (0)