// IsRetryableAPIError returns if this error is retryable or not
506471
func IsRetryableAPIError(err error) bool {
	return apierrs.IsTimeout(err) || apierrs.IsServerTimeout(err) || apierrs.IsTooManyRequests(err) || apierrs.IsInternalError(err)
}
322908
func IsRetryableNetworkError(err error) bool {
	if err == nil {
		return false
	}
	// get original error if it was wrapped
	err = argoerrs.Cause(err)
	errStr := err.Error()

	switch err.(type) {
	case net.Error:
		switch err.(type) {
		case *net.DNSError, *net.OpError, net.UnknownNetworkError:
			return true
		case *url.Error:
			// For a URL error, where it replies back "connection closed"
			// retry again.
			if strings.Contains(errStr, "Connection closed by foreign host") {
				return true
			}
		default:
			if strings.Contains(errStr, "net/http: TLS handshake timeout") {
				// If error is - tlsHandshakeTimeoutError, retry.
				return true
			} else if strings.Contains(errStr, "i/o timeout") {
				// If error is - tcp timeoutError, retry.
				return true
			} else if strings.Contains(errStr, "connection timed out") {
				// If err is a net.Dial timeout, retry.
				return true
			}
		}
	}
	return false
}
930871
func UseApiError(status int) bool {
	switch {
	case status > 199 && status < 300:
		return false
	case status == 304:
		return false
	case status == 0:
		return false
	}
	return true
}
730781
func (u once) AllowRetry(retryCount int, elapsed time.Duration) (bool, time.Duration) {
	if retryCount == 0 {
		return true, u.sleepBetweenRetry
	}
	return false, time.Duration(0)
}
1316441
func isVPCNotUsableError(err error) bool {
	err = errors.Cause(err)
	_, ok := err.(*vpcNotUsableError)
	return ok
}
626081
func (b *blockServerRemoteClientHandler) ShouldRetry(rpcName string, err error) bool {
	// Do not let connection.go's DoCommand retry any batch rpcs
	// since batchDowngradeReferences already handles retries.
	switch rpcName {
	case "keybase.1.block.delReferenceWithCount":
		return false
	case "keybase.1.block.archiveReferenceWithCount":
		return false
	}
	return kbfsblock.IsThrottleError(err)
}
544119
func (a *AbuseRateLimitError) GetRetryAfter() time.Duration {
	if a == nil || a.RetryAfter == nil {
		return 0
	}
	return *a.RetryAfter
}
756451
func NewStaticRetryableError(err error, maxAttempts, waitSeconds int) RetryableError {
	return &staticRetryableError{err, maxAttempts, time.Duration(waitSeconds)}
}
962472
func IsRetriableError(err error) bool {
	if e, ok := err.(interface {
		RetriableError() bool
	}); ok {
		return e.RetriableError()
	}
	if cause, ok := Cause(err).(*url.Error); ok {
		return cause.Temporary() || cause.Timeout()
	}
	if parent := parentOf(err); parent != nil {
		return IsRetriableError(parent)
	}
	return false
}
674979
func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
	if err == nil {
		return ErrNone
	}
	// Verify if the underlying error is signature mismatch.
	switch err {
	case errInvalidArgument:
		apiErr = ErrAdminInvalidArgument
	case errNoSuchUser:
		apiErr = ErrAdminNoSuchUser
	case errNoSuchPolicy:
		apiErr = ErrAdminNoSuchPolicy
	case errSignatureMismatch:
		apiErr = ErrSignatureDoesNotMatch
	case errInvalidRange:
		apiErr = ErrInvalidRange
	case errDataTooLarge:
		apiErr = ErrEntityTooLarge
	case errDataTooSmall:
		apiErr = ErrEntityTooSmall
	case auth.ErrInvalidAccessKeyLength:
		apiErr = ErrAdminInvalidAccessKey
	case auth.ErrInvalidSecretKeyLength:
		apiErr = ErrAdminInvalidSecretKey
	// SSE errors
	case errInvalidEncryptionParameters:
		apiErr = ErrInvalidEncryptionParameters
	case crypto.ErrInvalidEncryptionMethod:
		apiErr = ErrInvalidEncryptionMethod
	case crypto.ErrInvalidCustomerAlgorithm:
		apiErr = ErrInvalidSSECustomerAlgorithm
	case crypto.ErrMissingCustomerKey:
		apiErr = ErrMissingSSECustomerKey
	case crypto.ErrMissingCustomerKeyMD5:
		apiErr = ErrMissingSSECustomerKeyMD5
	case crypto.ErrCustomerKeyMD5Mismatch:
		apiErr = ErrSSECustomerKeyMD5Mismatch
	case errObjectTampered:
		apiErr = ErrObjectTampered
	case errEncryptedObject:
		apiErr = ErrSSEEncryptedObject
	case errInvalidSSEParameters:
		apiErr = ErrInvalidSSECustomerParameters
	case crypto.ErrInvalidCustomerKey, crypto.ErrSecretKeyMismatch:
		apiErr = ErrAccessDenied // no access without correct key
	case crypto.ErrIncompatibleEncryptionMethod:
		apiErr = ErrIncompatibleEncryptionMethod
	case errKMSNotConfigured:
		apiErr = ErrKMSNotConfigured
	case crypto.ErrKMSAuthLogin:
		apiErr = ErrKMSAuthFailure
	case errOperationTimedOut, context.Canceled, context.DeadlineExceeded:
		apiErr = ErrOperationTimedOut
	case errNetworkConnReset:
		apiErr = ErrSlowDown
	}

	// Compression errors
	switch err {
	case errInvalidDecompressedSize:
		apiErr = ErrInvalidDecompressedSize
	}

	if apiErr != ErrNone {
		// If there was a match in the above switch case.
		return apiErr
	}

	// etcd specific errors, a key is always a bucket for us return
	// ErrNoSuchBucket in such a case.
	if err == dns.ErrNoEntriesFound {
		return ErrNoSuchBucket
	}

	switch err.(type) {
	case StorageFull:
		apiErr = ErrStorageFull
	case hash.BadDigest:
		apiErr = ErrBadDigest
	case AllAccessDisabled:
		apiErr = ErrAllAccessDisabled
	case IncompleteBody:
		apiErr = ErrIncompleteBody
	case ObjectExistsAsDirectory:
		apiErr = ErrObjectExistsAsDirectory
	case PrefixAccessDenied:
		apiErr = ErrAccessDenied
	case ParentIsObject:
		apiErr = ErrParentIsObject
	case BucketNameInvalid:
		apiErr = ErrInvalidBucketName
	case BucketNotFound:
		apiErr = ErrNoSuchBucket
	case BucketAlreadyOwnedByYou:
		apiErr = ErrBucketAlreadyOwnedByYou
	case BucketNotEmpty:
		apiErr = ErrBucketNotEmpty
	case BucketAlreadyExists:
		apiErr = ErrBucketAlreadyExists
	case BucketExists:
		apiErr = ErrBucketAlreadyOwnedByYou
	case ObjectNotFound:
		apiErr = ErrNoSuchKey
	case ObjectAlreadyExists:
		apiErr = ErrMethodNotAllowed
	case ObjectNameInvalid:
		apiErr = ErrInvalidObjectName
	case InvalidUploadID:
		apiErr = ErrNoSuchUpload
	case InvalidPart:
		apiErr = ErrInvalidPart
	case InsufficientWriteQuorum:
		apiErr = ErrWriteQuorum
	case InsufficientReadQuorum:
		apiErr = ErrReadQuorum
	case UnsupportedDelimiter:
		apiErr = ErrNotImplemented
	case InvalidMarkerPrefixCombination:
		apiErr = ErrNotImplemented
	case InvalidUploadIDKeyCombination:
		apiErr = ErrNotImplemented
	case MalformedUploadID:
		apiErr = ErrNoSuchUpload
	case PartTooSmall:
		apiErr = ErrEntityTooSmall
	case SignatureDoesNotMatch:
		apiErr = ErrSignatureDoesNotMatch
	case hash.SHA256Mismatch:
		apiErr = ErrContentSHA256Mismatch
	case ObjectTooLarge:
		apiErr = ErrEntityTooLarge
	case ObjectTooSmall:
		apiErr = ErrEntityTooSmall
	case NotImplemented:
		apiErr = ErrNotImplemented
	case PartTooBig:
		apiErr = ErrEntityTooLarge
	case UnsupportedMetadata:
		apiErr = ErrUnsupportedMetadata
	case BucketPolicyNotFound:
		apiErr = ErrNoSuchBucketPolicy
	case *event.ErrInvalidEventName:
		apiErr = ErrEventNotification
	case *event.ErrInvalidARN:
		apiErr = ErrARNNotification
	case *event.ErrARNNotFound:
		apiErr = ErrARNNotification
	case *event.ErrUnknownRegion:
		apiErr = ErrRegionNotification
	case *event.ErrInvalidFilterName:
		apiErr = ErrFilterNameInvalid
	case *event.ErrFilterNamePrefix:
		apiErr = ErrFilterNamePrefix
	case *event.ErrFilterNameSuffix:
		apiErr = ErrFilterNameSuffix
	case *event.ErrInvalidFilterValue:
		apiErr = ErrFilterValueInvalid
	case *event.ErrDuplicateEventName:
		apiErr = ErrOverlappingConfigs
	case *event.ErrDuplicateQueueConfiguration:
		apiErr = ErrOverlappingFilterNotification
	case *event.ErrUnsupportedConfiguration:
		apiErr = ErrUnsupportedNotification
	case BackendDown:
		apiErr = ErrBackendDown
	case crypto.Error:
		apiErr = ErrObjectTampered
	default:
		var ie, iw int
		// This work-around is to handle the issue golang/go#30648
		if _, ferr := fmt.Fscanf(strings.NewReader(err.Error()),
			"request declared a Content-Length of %d but only wrote %d bytes",
			&ie, &iw); ferr != nil {
			apiErr = ErrInternalError
			// Make sure to log the errors which we cannot translate
			// to a meaningful S3 API errors. This is added to aid in
			// debugging unexpected/unhandled errors.
			logger.LogIf(ctx, err)
		} else if ie > iw {
			apiErr = ErrIncompleteBody
		} else {
			apiErr = ErrInternalError
			// Make sure to log the errors which we cannot translate
			// to a meaningful S3 API errors. This is added to aid in
			// debugging unexpected/unhandled errors.
			logger.LogIf(ctx, err)
		}
	}

	return apiErr
}
1318889
func IsNoResultsError(err error) bool {
	switch errType := errors.Cause(err).(type) {
	case NoResultsError:
		return errType.NoResultsError()
	default:
		return false
	}
}
1237328
func (i *impl) isRetryable(g status.Group, c int32) bool {
	for group, codes := range i.opts.RetryableCodes {
		if g != group {
			continue
		}
		for _, code := range codes {
			if status.Code(c) == code {
				return true
			}
		}
	}
	return false
}
1122946
func XapiError(err error, u string) *ProofAPIError {
	if ae, ok := err.(*APIError); ok {
		code := keybase1.ProofStatus_NONE
		switch ae.Code / 100 {
		case 3:
			code = keybase1.ProofStatus_HTTP_300
		case 4:
			if ae.Code == 429 {
				code = keybase1.ProofStatus_HTTP_429
			} else {
				code = keybase1.ProofStatus_HTTP_400
			}
		case 5:
			code = keybase1.ProofStatus_HTTP_500
		default:
			code = keybase1.ProofStatus_HTTP_OTHER
		}
		return NewProofAPIError(code, u, ae.Msg)
	}
	return NewProofAPIError(keybase1.ProofStatus_INTERNAL_ERROR, u, err.Error())
}
913435
func RetryTemporaryErr() RetryFn {
	return RetryIsErr(func(err error) bool {
		if terr, ok := err.(temporaryer); ok {
			return terr.Temporary()
		}
		return false
	})
}
509979
func WrapRecoverable(msg string, err error) error {
	return &RecoverableError{Err: msg, Recoverable: IsRecoverable(err)}
}
373043
func RetryIfPossible(ctx context.Context, g *libkb.GlobalContext, post func(ctx context.Context, attempt int) error) (err error) {
	defer g.CTraceTimed(ctx, "RetryIfPossible", func() error { return err })()
	const nRetries = 3
	for i := 0; i < nRetries; i++ {
		g.Log.CDebugf(ctx, "| RetryIfPossible(%v)", i)
		err = post(ctx, i)
		if isSigOldSeqnoError(err) {
			g.Log.CDebugf(ctx, "| retrying due to SigOldSeqnoError", i)
			continue
		}
		if isStaleBoxError(err) {
			g.Log.CDebugf(ctx, "| retrying due to StaleBoxError", i)
			continue
		}
		return err
	}
	g.Log.CDebugf(ctx, "| RetryIfPossible exhausted attempts")
	if err == nil {
		// Should never happen
		return fmt.Errorf("failed retryable team operation")
	}
	// Return the error from the final round
	return err
}
1370373
func NewRetryStrategyAPI(
	st *state.State,
	resources facade.Resources,
	authorizer facade.Authorizer,
) (*RetryStrategyAPI, error) {
	if !authorizer.AuthUnitAgent() && !authorizer.AuthApplicationAgent() {
		return nil, common.ErrPerm
	}

	model, err := st.Model()
	if err != nil {
		return nil, errors.Trace(err)
	}

	return &RetryStrategyAPI{
		st:    st,
		model: model,
		canAccess: func() (common.AuthFunc, error) {
			return authorizer.AuthOwner, nil
		},
		resources: resources,
	}, nil
}