From 75dfdaa80390d0a421648a259c48b96f87d4ec09 Mon Sep 17 00:00:00 2001 From: Markus Heiden Date: Thu, 19 May 2022 09:30:13 +0200 Subject: [PATCH] Add method to extract all errors of a partial failure status at once This is useful because getting all errors via their operation index is inefficient. In #getGoogleAdsErrors(long, GoogleAdsFailureT) the error paths for all failures are build just to pick those for the requested operation index. That leads creation of many ErrorPath objects for all not requested operation indexes which. Those are immediately discarded what leads to avoidable GC pressure. This can already be achieved with the current API, but I think it belongs into the error util. The code (Java 11) I currently use as supplement: status.getDetailsList().stream() .map(errorUtils::getGoogleAdsFailure) .map(errorUtils::getGoogleAdsErrors) .flatMap(List::stream) .collect(toSet()); --- .../lib/utils/AbstractErrorUtils.java | 62 +++++++++++++++++++ .../lib/utils/AbstractErrorUtilsTest.java | 31 ++++++++++ 2 files changed, 93 insertions(+) diff --git a/google-ads-stubs-lib/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java b/google-ads-stubs-lib/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java index 66ed48cf0a..86d0fc22dc 100644 --- a/google-ads-stubs-lib/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java +++ b/google-ads-stubs-lib/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java @@ -30,6 +30,68 @@ public abstract class AbstractErrorUtils< GoogleAdsErrorT extends Message, FieldPathElementT extends Message> { + /** + * Gets a list of all partial failure error messages for a given response. + * + *

For example, given the following Failure: + * + *

+   *   
+   *     errors {
+   *       message: "Too low."
+   *       location {
+   *         field_path_elements {
+   *           field_name: "operations"
+   *           index {
+   *             value: 1
+   *           }
+   *         }
+   *         field_path_elements {
+   *           field_name: "create"
+   *         }
+   *         field_path_elements {
+   *           field_name: "campaign"
+   *         }
+   *       }
+   *     }
+   *     errors {
+   *       message: "Too low."
+   *       location {
+   *         field_path_elements {
+   *           field_name: "operations"
+   *           index {
+   *             value: 2
+   *           }
+   *         }
+   *         field_path_elements {
+   *           field_name: "create"
+   *         }
+   *         field_path_elements {
+   *           field_name: "campaign"
+   *         }
+   *       }
+   *     }
+   *   
+   * 
+ * + * Two {@link GoogleAdsErrorT} instances would be returned for operation index 1 and 2. + * + * @param partialFailureStatus a partialFailure status, with the detail list containing {@link + * GoogleAdsFailureT} instances. + * @return a list containing all the {@link GoogleAdsErrorT} instances. + * @throws InvalidProtocolBufferException if not able to unpack the protocol buffer. This is most + * likely due to using the wrong version of ErrorUtils being used with the API response. + */ + public List getGoogleAdsErrors(Status partialFailureStatus) + throws InvalidProtocolBufferException { + List result = new ArrayList(); + for (Any detail : partialFailureStatus.getDetailsList()) { + GoogleAdsFailureT failure = getGoogleAdsFailure(detail); + result.addAll(getGoogleAdsErrors(failure)); + } + return result; + } + /** * Gets a list of all partial failure error messages for a given response. Operations are indexed * from 0. diff --git a/google-ads/src/test/java/com/google/ads/googleads/lib/utils/AbstractErrorUtilsTest.java b/google-ads/src/test/java/com/google/ads/googleads/lib/utils/AbstractErrorUtilsTest.java index feb5d702c0..f93946b326 100644 --- a/google-ads/src/test/java/com/google/ads/googleads/lib/utils/AbstractErrorUtilsTest.java +++ b/google-ads/src/test/java/com/google/ads/googleads/lib/utils/AbstractErrorUtilsTest.java @@ -15,6 +15,7 @@ package com.google.ads.googleads.lib.utils; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import com.google.ads.googleads.lib.test.errors.Int64Value; import com.google.ads.googleads.lib.test.errors.MockError; @@ -44,6 +45,36 @@ public static String[] parameters() { return new String[] {"operations", "mutate_operations"}; } + @Test + public void getGoogleAdsErrors_includesAll() throws InvalidProtocolBufferException { + MockPath pathIndex = + MockPath.newBuilder() + .setIndex(Int64Value.newBuilder().setValue(0)) + .setFieldName(operationsFieldName) + .build(); + MockError errorIndex = MockError.newBuilder().addLocation(pathIndex).build(); + MockFailure failureIndex = MockFailure.newBuilder().addErrors(errorIndex).build(); + + MockPath pathNoIndex = MockPath.newBuilder().setFieldName(operationsFieldName).build(); + MockError errorNoIndex = MockError.newBuilder().addLocation(pathNoIndex).build(); + MockFailure failureNoIndex = MockFailure.newBuilder().addErrors(errorNoIndex).build(); + + MockPath pathNoOperation = MockPath.newBuilder().setFieldName("someotherfield").build(); + MockError errorNoOperation = MockError.newBuilder().addLocation(pathNoOperation).build(); + MockFailure failureNoOperation = MockFailure.newBuilder().addErrors(errorNoOperation).build(); + + Status status = Status.newBuilder() + .addDetails(Any.pack(failureIndex)) + .addDetails(Any.pack(failureNoIndex)) + .addDetails(Any.pack(failureNoOperation)) + .build(); + List result = impl.getGoogleAdsErrors(status); + assertEquals(3, result.size()); + assertEquals(errorIndex, result.get(0)); + assertEquals(errorNoIndex, result.get(1)); + assertEquals(errorNoOperation, result.get(2)); + } + @Test public void getGoogleAdsErrors_includesWhen_operationSet() throws InvalidProtocolBufferException { MockPath path =