mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 01:53:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			108 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2015 The Kubernetes Authors.
 | 
						|
 | 
						|
Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
you may not use this file except in compliance with the License.
 | 
						|
You may obtain a copy of the License at
 | 
						|
 | 
						|
    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 | 
						|
Unless required by applicable law or agreed to in writing, software
 | 
						|
distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
See the License for the specific language governing permissions and
 | 
						|
limitations under the License.
 | 
						|
*/
 | 
						|
 | 
						|
package rest
 | 
						|
 | 
						|
import (
 | 
						|
	"net/url"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						|
	"k8s.io/client-go/util/flowcontrol"
 | 
						|
	"k8s.io/klog/v2"
 | 
						|
)
 | 
						|
 | 
						|
// Set of resp. Codes that we backoff for.
 | 
						|
// In general these should be errors that indicate a server is overloaded.
 | 
						|
// These shouldn't be configured by any user, we set them based on conventions
 | 
						|
// described in
 | 
						|
var serverIsOverloadedSet = sets.NewInt(429)
 | 
						|
var maxResponseCode = 499
 | 
						|
 | 
						|
type BackoffManager interface {
 | 
						|
	UpdateBackoff(actualUrl *url.URL, err error, responseCode int)
 | 
						|
	CalculateBackoff(actualUrl *url.URL) time.Duration
 | 
						|
	Sleep(d time.Duration)
 | 
						|
}
 | 
						|
 | 
						|
// URLBackoff struct implements the semantics on top of Backoff which
 | 
						|
// we need for URL specific exponential backoff.
 | 
						|
type URLBackoff struct {
 | 
						|
	// Uses backoff as underlying implementation.
 | 
						|
	Backoff *flowcontrol.Backoff
 | 
						|
}
 | 
						|
 | 
						|
// NoBackoff is a stub implementation, can be used for mocking or else as a default.
 | 
						|
type NoBackoff struct {
 | 
						|
}
 | 
						|
 | 
						|
func (n *NoBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode int) {
 | 
						|
	// do nothing.
 | 
						|
}
 | 
						|
 | 
						|
func (n *NoBackoff) CalculateBackoff(actualUrl *url.URL) time.Duration {
 | 
						|
	return 0 * time.Second
 | 
						|
}
 | 
						|
 | 
						|
func (n *NoBackoff) Sleep(d time.Duration) {
 | 
						|
	time.Sleep(d)
 | 
						|
}
 | 
						|
 | 
						|
// Disable makes the backoff trivial, i.e., sets it to zero.  This might be used
 | 
						|
// by tests which want to run 1000s of mock requests without slowing down.
 | 
						|
func (b *URLBackoff) Disable() {
 | 
						|
	klog.V(4).Infof("Disabling backoff strategy")
 | 
						|
	b.Backoff = flowcontrol.NewBackOff(0*time.Second, 0*time.Second)
 | 
						|
}
 | 
						|
 | 
						|
// baseUrlKey returns the key which urls will be mapped to.
 | 
						|
// For example, 127.0.0.1:8080/api/v2/abcde -> 127.0.0.1:8080.
 | 
						|
func (b *URLBackoff) baseUrlKey(rawurl *url.URL) string {
 | 
						|
	// Simple implementation for now, just the host.
 | 
						|
	// We may backoff specific paths (i.e. "pods") differentially
 | 
						|
	// in the future.
 | 
						|
	host, err := url.Parse(rawurl.String())
 | 
						|
	if err != nil {
 | 
						|
		klog.V(4).Infof("Error extracting url: %v", rawurl)
 | 
						|
		panic("bad url!")
 | 
						|
	}
 | 
						|
	return host.Host
 | 
						|
}
 | 
						|
 | 
						|
// UpdateBackoff updates backoff metadata
 | 
						|
func (b *URLBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode int) {
 | 
						|
	// range for retry counts that we store is [0,13]
 | 
						|
	if responseCode > maxResponseCode || serverIsOverloadedSet.Has(responseCode) {
 | 
						|
		b.Backoff.Next(b.baseUrlKey(actualUrl), b.Backoff.Clock.Now())
 | 
						|
		return
 | 
						|
	} else if responseCode >= 300 || err != nil {
 | 
						|
		klog.V(4).Infof("Client is returning errors: code %v, error %v", responseCode, err)
 | 
						|
	}
 | 
						|
 | 
						|
	//If we got this far, there is no backoff required for this URL anymore.
 | 
						|
	b.Backoff.Reset(b.baseUrlKey(actualUrl))
 | 
						|
}
 | 
						|
 | 
						|
// CalculateBackoff takes a url and back's off exponentially,
 | 
						|
// based on its knowledge of existing failures.
 | 
						|
func (b *URLBackoff) CalculateBackoff(actualUrl *url.URL) time.Duration {
 | 
						|
	return b.Backoff.Get(b.baseUrlKey(actualUrl))
 | 
						|
}
 | 
						|
 | 
						|
func (b *URLBackoff) Sleep(d time.Duration) {
 | 
						|
	b.Backoff.Clock.Sleep(d)
 | 
						|
}
 |