diff options
author | Wim <wim@42.be> | 2021-12-12 00:05:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-12 00:05:15 +0100 |
commit | 3893a035be347a7687a41d2054dd1b274d3a0504 (patch) | |
tree | dfe4a3bf72a0a6356e51bd8fc2e88e9a26e52331 /vendor/github.com/minio/minio-go/v7/api.go | |
parent | 658bdd9faa835660ae407331732e9d93d8f6443b (diff) | |
download | matterbridge-msglm-3893a035be347a7687a41d2054dd1b274d3a0504.tar.gz matterbridge-msglm-3893a035be347a7687a41d2054dd1b274d3a0504.tar.bz2 matterbridge-msglm-3893a035be347a7687a41d2054dd1b274d3a0504.zip |
Update dependencies/vendor (#1659)
Diffstat (limited to 'vendor/github.com/minio/minio-go/v7/api.go')
-rw-r--r-- | vendor/github.com/minio/minio-go/v7/api.go | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/vendor/github.com/minio/minio-go/v7/api.go b/vendor/github.com/minio/minio-go/v7/api.go index 44660ab6..c8550ef1 100644 --- a/vendor/github.com/minio/minio-go/v7/api.go +++ b/vendor/github.com/minio/minio-go/v7/api.go @@ -34,6 +34,7 @@ import ( "runtime" "strings" "sync" + "sync/atomic" "time" md5simd "github.com/minio/md5-simd" @@ -90,6 +91,10 @@ type Client struct { // Factory for MD5 hash functions. md5Hasher func() md5simd.Hasher sha256Hasher func() md5simd.Hasher + + healthCheckCh chan struct{} + healthCheck int32 + lastOnline time.Time } // Options for New method @@ -108,7 +113,7 @@ type Options struct { // Global constants. const ( libraryName = "minio-go" - libraryVersion = "v7.0.11" + libraryVersion = "v7.0.14" ) // User Agent should always following the below style. @@ -305,6 +310,10 @@ func privateNew(endpoint string, opts *Options) (*Client, error) { // Sets bucket lookup style, whether server accepts DNS or Path lookup. Default is Auto - determined // by the SDK. When Auto is specified, DNS lookup is used for Amazon/Google cloud endpoints and Path for all other endpoints. clnt.lookup = opts.BucketLookup + + // healthcheck is not initialized + clnt.healthCheck = unknown + // Return. return clnt, nil } @@ -387,6 +396,72 @@ func (c *Client) hashMaterials(isMd5Requested bool) (hashAlgos map[string]md5sim return hashAlgos, hashSums } +const ( + unknown = -1 + offline = 0 + online = 1 +) + +// IsOnline returns true if healthcheck enabled and client is online +func (c *Client) IsOnline() bool { + switch atomic.LoadInt32(&c.healthCheck) { + case online, unknown: + return true + } + return false +} + +// IsOffline returns true if healthcheck enabled and client is offline +func (c *Client) IsOffline() bool { + return !c.IsOnline() +} + +// HealthCheck starts a healthcheck to see if endpoint is up. Returns a context cancellation function +// and and error if health check is already started +func (c *Client) HealthCheck(hcDuration time.Duration) (context.CancelFunc, error) { + if atomic.LoadInt32(&c.healthCheck) == online { + return nil, fmt.Errorf("health check running already") + } + if hcDuration < 1*time.Second { + return nil, fmt.Errorf("health check duration should be atleast 1 second") + } + ctx, cancelFn := context.WithCancel(context.Background()) + c.healthCheckCh = make(chan struct{}) + atomic.StoreInt32(&c.healthCheck, online) + probeBucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "probe-health-") + go func(duration time.Duration) { + timer := time.NewTimer(duration) + defer timer.Stop() + for { + select { + case <-ctx.Done(): + close(c.healthCheckCh) + atomic.StoreInt32(&c.healthCheck, unknown) + return + case <-timer.C: + + timer.Reset(duration) + // Do health check the first time and ONLY if the connection is marked offline + if c.IsOffline() || c.lastOnline.IsZero() { + _, err := c.getBucketLocation(context.Background(), probeBucketName) + if err != nil && IsNetworkOrHostDown(err, false) { + atomic.StoreInt32(&c.healthCheck, offline) + } + switch ToErrorResponse(err).Code { + case "NoSuchBucket", "AccessDenied", "": + c.lastOnline = time.Now() + atomic.StoreInt32(&c.healthCheck, online) + } + } + case <-c.healthCheckCh: + // set offline if client saw a network error + atomic.StoreInt32(&c.healthCheck, offline) + } + } + }(hcDuration) + return cancelFn, nil +} + // requestMetadata - is container for all the values to make a request. type requestMetadata struct { // If set newRequest presigns the URL. @@ -565,12 +640,25 @@ func (c Client) executeMethod(ctx context.Context, method string, metadata reque if isS3CodeRetryable(errResponse.Code) { continue // Retry. } + + if atomic.LoadInt32(&c.healthCheck) != unknown && IsNetworkOrHostDown(err, false) { + select { + case c.healthCheckCh <- struct{}{}: + default: + } + } return nil, err } - // Initiate the request. res, err = c.do(req) if err != nil { + if atomic.LoadInt32(&c.healthCheck) != unknown && IsNetworkOrHostDown(err, false) { + select { + case c.healthCheckCh <- struct{}{}: + default: + } + } + if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { return nil, err } |