Skip to content

Commit fd07533

Browse files
Fix: adjusting retry logic to avoid retrying successful job creation (#1879)
#1744 introduced retrying 200 responses, but the regex that we are using is too broad: [".*exceed.*rate.limit."] and in some cases it may catch a valid response. The issue is that the current logic is scanning the whole response. In this PR the retry logic is modified to specifically check the error message from the response. For this purpose parsing logic was developed to extract error messages from responses. This logic is specifically designed for the [jobs.insert method response](https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/insert#response-body) (only case observed so far where a response with status code 200 might also return an error message).
1 parent 1bc9188 commit fd07533

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

‎google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryRetryAlgorithm.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import com.google.api.gax.retrying.TimedAttemptSettings;
2626
import com.google.api.gax.retrying.TimedRetryAlgorithm;
2727
import com.google.api.gax.retrying.TimedRetryAlgorithmWithContext;
28+
import com.google.gson.JsonObject;
29+
import com.google.gson.JsonParser;
2830
import java.util.Iterator;
2931
import java.util.UUID;
3032
import java.util.concurrent.CancellationException;
@@ -107,9 +109,10 @@ private boolean shouldRetryBasedOnBigQueryRetryConfig(
107109
/*
108110
In some cases error messages may come without an exception
109111
e.g. status code 200 with a rate limit exceeded for job create
110-
in these cases there is now previousThrowable so we need to check previousResponse
112+
in these cases there is no previousThrowable so we need
113+
to check for error messages in previousResponse
111114
*/
112-
errorDesc = previousResponse.toString();
115+
errorDesc = getErrorDescFromResponse(previousResponse);
113116
}
114117

115118
if (errorDesc != null) {
@@ -212,4 +215,28 @@ private TimedAttemptSettings createNextAttemptBasedOnTiming(
212215
}
213216
return getTimedAlgorithm().createNextAttempt(previousSettings);
214217
}
218+
219+
private String getErrorDescFromResponse(ResponseT previousResponse) {
220+
/*
221+
error messages may come without an exception and must be extracted from response
222+
following logic based on response body of jobs.insert method, so far the only
223+
known case where a response with status code 200 may contain an error message
224+
*/
225+
try {
226+
JsonObject responseJson =
227+
JsonParser.parseString(previousResponse.toString()).getAsJsonObject();
228+
if (responseJson.has("status") && responseJson.getAsJsonObject("status").has("errorResult")) {
229+
return responseJson
230+
.getAsJsonObject("status")
231+
.getAsJsonObject("errorResult")
232+
.get("message")
233+
.toString();
234+
} else {
235+
return null;
236+
}
237+
} catch (Exception e) {
238+
// exceptions here implies no error message present in response, returning null
239+
return null;
240+
}
241+
}
215242
}

0 commit comments

Comments
 (0)