|
6 | 6 | "log"
|
7 | 7 | "net"
|
8 | 8 | "net/url"
|
| 9 | + "regexp" |
9 | 10 | "strings"
|
10 | 11 |
|
11 | 12 | "google.golang.org/api/googleapi"
|
@@ -45,7 +46,7 @@ var defaultErrorRetryPredicates = []RetryErrorPredicateFunc{
|
45 | 46 | // reads, causing significant failure for our CI and for large customers.
|
46 | 47 | // GCE returns the wrong error code, as this should be a 429, which we retry
|
47 | 48 | // already.
|
48 |
| - is403ReadRequestsForMinuteError, |
| 49 | + is403QuotaExceededPerMinuteError, |
49 | 50 | }
|
50 | 51 |
|
51 | 52 | /** END GLOBAL ERROR RETRY PREDICATES HERE **/
|
@@ -127,15 +128,18 @@ func isSubnetworkUnreadyError(err error) (bool, string) {
|
127 | 128 |
|
128 | 129 | // GCE (and possibly other APIs) incorrectly return a 403 rather than a 429 on
|
129 | 130 | // rate limits.
|
130 |
| -func is403ReadRequestsForMinuteError(err error) (bool, string) { |
| 131 | +func is403QuotaExceededPerMinuteError(err error) (bool, string) { |
131 | 132 | gerr, ok := err.(*googleapi.Error)
|
132 | 133 | if !ok {
|
133 | 134 | return false, ""
|
134 | 135 | }
|
135 |
| - |
136 |
| - if gerr.Code == 403 && strings.Contains(gerr.Body, "Quota exceeded for quota metric") && strings.Contains(gerr.Body, "Read requests per minute") { |
137 |
| - log.Printf("[DEBUG] Dismissed an error as retryable based on error code 403 and error message 'Quota exceeded for quota metric' on metric `Read requests per minute`: %s", err) |
138 |
| - return true, "Read requests per minute" |
| 136 | + var QuotaRegex = regexp.MustCompile(`Quota exceeded for quota metric '(?P<Metric>.*)' and limit '(?P<Limit>.* per minute)' of service`) |
| 137 | + if gerr.Code == 403 && QuotaRegex.MatchString(gerr.Body) { |
| 138 | + matches := QuotaRegex.FindStringSubmatch(gerr.Body) |
| 139 | + metric := matches[QuotaRegex.SubexpIndex("Metric")] |
| 140 | + limit := matches[QuotaRegex.SubexpIndex("Limit")] |
| 141 | + log.Printf("[DEBUG] Dismissed an error as retryable based on error code 403 and error message 'Quota exceeded for quota metric `%s`: %s", metric, err) |
| 142 | + return true, fmt.Sprintf("Waiting for quota limit %s to refresh", limit) |
139 | 143 | }
|
140 | 144 | return false, ""
|
141 | 145 | }
|
@@ -260,17 +264,6 @@ func isBigqueryIAMQuotaError(err error) (bool, string) {
|
260 | 264 | return false, ""
|
261 | 265 | }
|
262 | 266 |
|
263 |
| -// Retry if operation returns a 403 with the message for |
264 |
| -// exceeding the quota limit for 'OperationReadGroup' |
265 |
| -func isOperationReadQuotaError(err error) (bool, string) { |
266 |
| - if gerr, ok := err.(*googleapi.Error); ok { |
267 |
| - if gerr.Code == 403 && strings.Contains(gerr.Body, "Quota exceeded for quota group") { |
268 |
| - return true, "Waiting for quota to refresh" |
269 |
| - } |
270 |
| - } |
271 |
| - return false, "" |
272 |
| -} |
273 |
| - |
274 | 267 | // Retry if Monitoring operation returns a 409 with a specific message for
|
275 | 268 | // concurrent operations.
|
276 | 269 | func isMonitoringConcurrentEditError(err error) (bool, string) {
|
|
0 commit comments