1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
12 "git.arvados.org/arvados.git/lib/cloud"
13 "github.com/sirupsen/logrus"
16 type throttle struct {
22 // CheckRateLimitError checks whether the given error is a
23 // cloud.RateLimitError, and if so, ensures Error() returns a non-nil
24 // error until the rate limiting holdoff period expires.
26 // If a notify func is given, it will be called after the holdoff
28 func (thr *throttle) CheckRateLimitError(err error, logger logrus.FieldLogger, callType string, notify func()) {
29 rle, ok := err.(cloud.RateLimitError)
33 until := rle.EarliestRetry()
34 if !until.After(time.Now()) {
37 dur := until.Sub(time.Now())
38 logger.WithFields(logrus.Fields{
42 }).Info("suspending remote calls due to rate-limit error")
43 thr.ErrorUntil(fmt.Errorf("remote calls are suspended for %s, until %s", dur, until), until, notify)
46 func (thr *throttle) ErrorUntil(err error, until time.Time, notify func()) {
48 defer thr.mtx.Unlock()
49 thr.err, thr.until = err, until
51 time.AfterFunc(until.Sub(time.Now()), notify)
55 func (thr *throttle) Error() error {
57 defer thr.mtx.Unlock()
58 if thr.err != nil && time.Now().After(thr.until) {
64 type throttledInstanceSet struct {
66 throttleCreate throttle
67 throttleInstances throttle