func shouldRetryWithWait()

in compute/compute.go [253:297]


func shouldRetryWithWait(tripper http.RoundTripper, err error, multiplier int) bool {
	if err == nil {
		return false
	}
	tkValid := true
	trans, ok := tripper.(*oauth2.Transport)
	if ok {
		if tk, err := trans.Source.Token(); err == nil {
			tkValid = tk.Valid()
		}
	}

	apiErr, ok := err.(*googleapi.Error)
	var retry bool
	switch {
	case !ok && (strings.Contains(err.Error(), "connection reset by peer") || strings.Contains(err.Error(), "unexpected EOF")):
		retry = true
	case !ok && (strings.Contains(err.Error(), "server sent GOAWAY") || strings.Contains(err.Error(), "ENHANCE_YOUR_CALM")):
		// The wait operation can return GOAWAY/ENHANCE_YOUR_CALM messages, so doubling the wait multiplier as it based on the retry count.
		multiplier = multiplier * 2
		retry = true
	case !ok && tkValid:
		// Not a googleapi.Error and the token is still valid.
		return false
	case apiErr.Code >= 500 && apiErr.Code <= 599:
		retry = true
	case apiErr.Code >= 429:
		// Too many API requests.
		retry = true
	case apiErr.Code == 403 && strings.Contains(err.Error(), "rateLimitExceeded"):
		// Quota errors are reported as 403.
		// Generally we don't want to retry on quota errors, but if it's quota on rate (GetSerialPortOutput) - we should.
		retry = true
	case !tkValid:
		// This was probably a failure to get new token from metadata server.
		retry = true
	}
	if !retry {
		return false
	}

	sleep := (time.Duration(rand.Intn(1000))*time.Millisecond + 1*time.Second) * time.Duration(multiplier)
	time.Sleep(sleep)
	return true
}