public static ThrowableInfo isRetryableException()

in services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/helpers/ControllerExceptionHelper.java [47:137]


    public static ThrowableInfo isRetryableException(Throwable throwable) {

        Class exceptionClass = throwable.getClass();

        // 1. Check if it's any type of rate limit exception. If so, retry.

        // Thrown by DLP
        if (StatusRuntimeException.class.isAssignableFrom(exceptionClass)) {
            StatusRuntimeException statusRuntimeException = (StatusRuntimeException) throwable;
            if (statusRuntimeException.getStatus() != null && statusRuntimeException.getStatus().equals(Status.RESOURCE_EXHAUSTED)) {
                return new ThrowableInfo(throwable, true, "Retryable: 'status' = RESOURCE_EXHAUSTED assignable from StatusRuntimeException");
            }
        }

        // Thrown by BigQuery
        if (BigQueryException.class.isAssignableFrom(exceptionClass)) {
            BigQueryException bigQueryException = (BigQueryException) throwable;
            // when hitting the concurrent interactive queries
            // bigQueryException.getReason() is sometimes null.
            if (bigQueryException.getReason() != null && bigQueryException.getReason().equals("jobRateLimitExceeded")) {
                return new ThrowableInfo(throwable,
                        true,
                        "Retryable: 'reason' = jobRateLimitExceeded assignable from BigQueryException");
            }
            // handling "Exceeded rate limits: too many api requests per user per method for this user_method"
            if (bigQueryException.getReason() != null && bigQueryException.getReason().equals("rateLimitExceeded")) {
                return new ThrowableInfo(throwable,
                        true,
                        "Retryable: 'reason' = rateLimitExceeded assignable from BigQueryException");
            }

            // handling transit internalError https://cloud.google.com/bigquery/docs/error-messages#errortable
            if (bigQueryException.getCode() == 500 || bigQueryException.getCode() == 503) {
                return new ThrowableInfo(throwable,
                        true,
                        String.format("Retryable: 'code' = %s assignable from BigQueryException",
                                bigQueryException.getCode()));
            }

            // handling transit internalError https://cloud.google.com/bigquery/docs/error-messages#errortable
            if (bigQueryException.getReason() != null && bigQueryException.getReason().equals("internalError")
            ) {
                return new ThrowableInfo(throwable,
                        true,
                        String.format("Retryable: 'reason' = %s assignable from BigQueryException",
                                bigQueryException.getReason()));
            }
        }

        // BaseServiceException Thrown by BigQuery
        if (BaseServiceException.class.isAssignableFrom(exceptionClass)) {
            BaseServiceException baseServiceException = (BaseServiceException) throwable;
            if (baseServiceException.getCode() == 429) {
                return new ThrowableInfo(throwable, true, "Retryable: 'code' = 429 assignable from BaseServiceException");
            }
        }

        // 2. check if the exception inherits (at any level) from any Retryable Exception that we explicitly define
        for (Class retryableExClass : RETRYABLE_EXCEPTIONS) {
            if (retryableExClass.isAssignableFrom(exceptionClass)) {
                return new ThrowableInfo(throwable, true, String.format("Retryable: isAssignableFrom %s ", retryableExClass.getName()));
            }
        }

        // 3. check if the exception is caused by a Retryable Exception
        for (Class retryableExClass : RETRYABLE_EXCEPTIONS) {
            if (retryableExClass.isAssignableFrom(exceptionClass)) {
                return new ThrowableInfo(throwable, true, String.format("Retryable: isAssignableFrom %s ", retryableExClass.getName()));
            }
        }

        // 4. Check if it's any type of isRetryable. If so, retry.

        // Thrown by BigQuery:
        // Base class for all gcp service exceptions.
        // Check if it's a retryable BaseServiceException
        if (BaseServiceException.class.isAssignableFrom(exceptionClass)) {
            BaseServiceException baseServiceException = (BaseServiceException) throwable;
            return new ThrowableInfo(throwable, baseServiceException.isRetryable(), String.format("Check: isAssignableFrom BaseServiceException"));
        }

        // Check if it's Retryable ApiException
        if (ApiException.class.isAssignableFrom(exceptionClass)) {
            ApiException apiEx = (ApiException) throwable;
            return new ThrowableInfo(throwable, apiEx.isRetryable(), String.format("Check: isAssignableFrom BaseServiceException"));
        }

        // if not, log and ACK so that it's not retried
        return new ThrowableInfo(throwable, false, String.format(""));

    }