// NewClient creates new Vultr API client. Options are optional and can be nil. func NewClient(apiKey string, options *Options) *Client { userAgent := "vultr-go/" + Version client := http.DefaultClient endpoint, _ := url.Parse(DefaultEndpoint) rate := 1 * time.Second if options != nil { if options.HTTPClient != nil { client = options.HTTPClient } if options.UserAgent != "" { userAgent = options.UserAgent } if options.Endpoint != "" { endpoint, _ = url.Parse(options.Endpoint) } if options.RateLimitation != 0 { rate = options.RateLimitation } } return &Client{ UserAgent: userAgent, client: client, Endpoint: endpoint, APIKey: apiKey, bucket: tokenbucket.NewBucket(rate, 1), } }
// Test that a bucket that is empty blocks execution for the correct amount of time func Test_BucketCreation(t *testing.T) { // Create a bucket with capacity 3, that adds tokens every 4 seconds const RATE = 4 * time.Second const CAPACITY = 3 const ERROR = 500 * time.Millisecond const EXPECTED_DURATION = RATE * CAPACITY b := tokenbucket.NewBucket(RATE, CAPACITY) // Ensure that the bucket is empty <-b.SpendToken(1) <-b.SpendToken(1) <-b.SpendToken(1) <-b.SpendToken(1) // Spending three times on an empty bucket should take 12 seconds // (Take the average across three, due to imprecision/scheduling) before := time.Now() <-b.SpendToken(1) <-b.SpendToken(1) <-b.SpendToken(1) after := time.Now() lower := EXPECTED_DURATION - ERROR upper := EXPECTED_DURATION + ERROR if diff := after.Sub(before); diff < lower || diff > upper { t.Errorf("Waited %s seconds, though really should have waited between %s and %s", diff.String(), lower.String(), upper.String()) } }
func Example_BucketUse() { // Allow a new action every 5 seconds, with a maximum of 3 "in the bank" bucket := tokenbucket.NewBucket(5*time.Second, 3) // To perform a regulated action, we must spend a token // RegulatedAction will not be performed until the bucket contains enough tokens <-bucket.SpendToken(1) RegulatedAction() }
// Test that a bucket that is full does not block execution func Test_BucketBuffering(t *testing.T) { // Create a bucket with capacity 3, that adds tokens every 4 seconds const RATE = 4 * time.Second const CAPACITY = 3 const ERROR = 500 * time.Millisecond b := tokenbucket.NewBucket(RATE, CAPACITY) // Allow the bucket enough time to fill to capacity time.Sleep(CAPACITY * RATE) // Check that we can empty the bucket without wasting any time before := time.Now() <-b.SpendToken(1) <-b.SpendToken(1) <-b.SpendToken(1) after := time.Now() if diff := after.Sub(before); diff > RATE { t.Errorf("Waited %d seconds, though this should have been nearly instantaneous", diff) } }
//EnableThrottling is used to enable query throttling with the tokenbucket algorithm func (a *API) EnableThrottling(rate time.Duration, bufferSize int64) { a.bucket = tokenbucket.NewBucket(rate, bufferSize) }
// Enable query throttling using the tokenbucket algorithm func (c *TwitterApi) EnableThrottling(rate time.Duration, bufferSize int64) { c.bucket = tokenbucket.NewBucket(rate, bufferSize) }