DefaultProxyTLSHandshakeTimeout = 10 * time.Second
DefaultProxyKeepAlive = 120 * time.Second
+ DefaultRetryDelay = 2 * time.Second // see KeepClient.RetryDelay
+ MinimumRetryDelay = time.Millisecond
+
rootCacheDir = "/var/cache/arvados/keep"
userCacheDir = ".cache/arvados/keep" // relative to HOME
)
multipleResponseError
}
+func (*ErrNotFound) HTTPStatus() int { return http.StatusNotFound }
+
type InsufficientReplicasError struct{ error }
type OversizeBlockError struct{ error }
XKeepReplicasStored = "X-Keep-Replicas-Stored"
XKeepStorageClasses = "X-Keep-Storage-Classes"
XKeepStorageClassesConfirmed = "X-Keep-Storage-Classes-Confirmed"
+ XKeepSignature = "X-Keep-Signature"
+ XKeepLocator = "X-Keep-Locator"
)
type HTTPClient interface {
// KeepClient holds information about Arvados and Keep servers.
type KeepClient struct {
- Arvados *arvadosclient.ArvadosClient
- Want_replicas int
- localRoots map[string]string
- writableLocalRoots map[string]string
- gatewayRoots map[string]string
- lock sync.RWMutex
- HTTPClient HTTPClient
- Retries int
+ Arvados *arvadosclient.ArvadosClient
+ Want_replicas int
+ localRoots map[string]string
+ writableLocalRoots map[string]string
+ gatewayRoots map[string]string
+ lock sync.RWMutex
+ HTTPClient HTTPClient
+
+ // Number of times to automatically retry a read/write
+ // operation after a transient failure.
+ Retries int
+
+ // Initial maximum delay for automatic retry. If zero,
+ // DefaultRetryDelay is used. The delay after attempt N
+ // (0-based) will be a random duration between
+ // MinimumRetryDelay and RetryDelay * 2^N, not to exceed a cap
+ // of RetryDelay * 10.
+ RetryDelay time.Duration
+
RequestID string
StorageClasses []string
DefaultStorageClasses []string // Set by cluster's exported config
gatewayRoots: kc.gatewayRoots,
HTTPClient: kc.HTTPClient,
Retries: kc.Retries,
+ RetryDelay: kc.RetryDelay,
RequestID: kc.RequestID,
StorageClasses: kc.StorageClasses,
DefaultStorageClasses: kc.DefaultStorageClasses,
Retries: 2,
}
err = kc.loadDefaultClasses()
- if err != nil {
- DebugPrintf("DEBUG: Unable to load the default storage classes cluster config")
+ if err != nil && arv.Logger != nil {
+ arv.Logger.WithError(err).Debug("unable to load the default storage classes cluster config")
}
return kc
}
var errs []string
+ delay := delayCalculator{InitialMaxDelay: kc.RetryDelay}
triesRemaining := 1 + kc.Retries
serversToTry := kc.getSortedRoots(locator)
return nil, expectLength, url, resp.Header, nil
}
serversToTry = retryList
+ if len(serversToTry) > 0 && triesRemaining > 0 {
+ time.Sleep(delay.Next())
+ }
+ }
+ if kc.Arvados.Logger != nil {
+ kc.Arvados.Logger.Debugf("DEBUG: %s %s failed: %v", method, locator, errs)
}
- DebugPrintf("DEBUG: %s %s failed: %v", method, locator, errs)
var err error
if count404 == numServers {
Dir: cachedir,
MaxSize: kc.DiskCacheSize,
KeepGateway: backend,
+ Logger: kc.Arvados.Logger,
}
}
return kc.gatewayStack
return reqIDGen.Next()
}
+func (kc *KeepClient) debugf(format string, args ...interface{}) {
+ if kc.Arvados.Logger == nil {
+ return
+ }
+ kc.Arvados.Logger.Debugf(format, args...)
+}
+
type Locator struct {
Hash string
Size int // -1 if data size is not known