-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from reugn/develop
v0.2.0
- Loading branch information
Showing
22 changed files
with
701 additions
and
413 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: Build | ||
|
||
on: | ||
push: | ||
branches: | ||
- '**' | ||
pull_request: | ||
branches: | ||
- master | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
go-version: [1.19.x, 1.22.x] | ||
steps: | ||
- name: Setup Go | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
|
||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
|
||
- name: Run coverage | ||
run: go test -race ./... -coverprofile=coverage.out -covermode=atomic | ||
|
||
- name: Upload coverage to Codecov | ||
if: ${{ matrix.go-version == '1.19.x' }} | ||
uses: codecov/codecov-action@v4 | ||
with: | ||
token: ${{ secrets.CODECOV_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: golangci-lint | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
|
||
permissions: | ||
contents: read | ||
|
||
jobs: | ||
golangci: | ||
name: lint | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
|
||
- uses: actions/setup-go@v5 | ||
with: | ||
go-version: '1.22' | ||
cache: false | ||
|
||
- name: golangci-lint | ||
uses: golangci/golangci-lint-action@v4 | ||
with: | ||
version: v1.56 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
.idea/ | ||
.vscode/ | ||
.vscode/ | ||
coverage.out | ||
go.work |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
linters: | ||
disable-all: true | ||
enable: | ||
- dupl | ||
- errcheck | ||
- errorlint | ||
- exportloopref | ||
- funlen | ||
- gci | ||
- goconst | ||
- gocritic | ||
- gocyclo | ||
- gofmt | ||
- goimports | ||
- gosimple | ||
- govet | ||
- ineffassign | ||
- lll | ||
- misspell | ||
- prealloc | ||
- revive | ||
- staticcheck | ||
- stylecheck | ||
- typecheck | ||
- unconvert | ||
- unparam | ||
- unused | ||
|
||
issues: | ||
exclude-rules: | ||
- path: _test\.go | ||
linters: | ||
- unparam | ||
- funlen |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,95 @@ | ||
<h1 align="center">equalizer</h1> | ||
<p align="center"> | ||
<a href="https://travis-ci.org/reugn/equalizer"><img src="https://travis-ci.org/reugn/equalizer.svg?branch=master"></a> | ||
<a href="https://github.com/reugn/equalizer/actions/workflows/build.yml"><img src="https://github.com/reugn/equalizer/actions/workflows/build.yml/badge.svg"></a> | ||
<a href="https://pkg.go.dev/github.com/reugn/equalizer"><img src="https://pkg.go.dev/badge/github.com/reugn/equalizer"></a> | ||
<a href="https://goreportcard.com/report/github.com/reugn/equalizer"><img src="https://goreportcard.com/badge/github.com/reugn/equalizer"></a> | ||
<a href="https://codecov.io/gh/reugn/equalizer"><img src="https://codecov.io/gh/reugn/equalizer/branch/master/graph/badge.svg"></a> | ||
</p> | ||
<p align="center">A rate limiters package for Go.</p> | ||
|
||
Pick one of the rate limiters to throttle requests and control quota. | ||
The `equalizer` package provides a set of simple and easy-to-use rate limiters for Go. | ||
These rate limiters can be used to limit the rate of requests to any resource, such as a database, | ||
API, or file. | ||
|
||
The package includes the following rate limiters: | ||
* [Equalizer](#equalizer) | ||
* [Slider](#slider) | ||
* [TokenBucket](#tokenbucket) | ||
* [Token Bucket](#token-bucket) | ||
|
||
## Equalizer | ||
`Equalizer` is a rate limiter that manages quota based on previous requests' statuses and slows down or accelerates accordingly. | ||
`Equalizer` is a rate limiter that adjusts the rate of requests based on the outcomes of previous requests. | ||
If previous attempts have failed, Equalizer will slow down the rate of requests to avoid overloading the system. | ||
Conversely, if previous attempts have been successful, Equalizer will accelerate the rate of requests to make | ||
the most of the available capacity. | ||
|
||
### Usage | ||
### Usage Example | ||
```go | ||
// a random offset manager | ||
offset := equalizer.NewRandomOffset(96) | ||
|
||
// an Equalizer with the bitmap size of 96 with 16 reserved | ||
// positive bits and the random offset manager | ||
// an Equalizer with a bitmap size of 96, 16 reserved positive bits, and the random offset manager | ||
eq := equalizer.NewEqualizer(96, 16, offset) | ||
|
||
// non-blocking quota request | ||
haveQuota := eq.Ask() | ||
|
||
// update with ten previous successful requests | ||
eq.Notify(true, 10) | ||
haveQuota := eq.TryAcquire() | ||
// update on the successful request | ||
eq.Success(1) | ||
``` | ||
|
||
### Benchmarks | ||
```sh | ||
BenchmarkEqualizerShortAskStep-16 30607452 37.5 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizerShortAskRandom-16 31896340 34.5 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizerShortNotify-16 12715494 81.9 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizerLongAskStep-16 34627239 35.4 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizerLongAskRandom-16 32399748 34.0 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizerLongNotify-16 59935 20343 ns/op 0 B/op 0 allocs/op | ||
```console | ||
BenchmarkEqualizer_ShortTryAcquireStep-16 31538967 38.33 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizer_ShortTryAcquireRandom-16 37563639 31.66 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizer_ShortNotify-16 29519719 40.43 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizer_LongTryAcquireStep-16 32084402 38.36 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizer_LongTryAcquireRandom-16 39996501 30.37 ns/op 0 B/op 0 allocs/op | ||
BenchmarkEqualizer_LongNotify-16 29648655 40.46 ns/op 0 B/op 0 allocs/op | ||
``` | ||
|
||
## Slider | ||
`Slider` rate limiter is based on a sliding window with a specified quota capacity. | ||
Implements the `Limiter` interface. | ||
`Slider` tracks the number of requests that have been processed in a recent time window. | ||
If the number of requests exceeds the limit, the rate limiter will block new requests until the window | ||
has moved forward. | ||
Implements the `equalizer.Limiter` interface. | ||
|
||
### Usage | ||
### Usage Example | ||
```go | ||
// a Slider with one second window size, 100 millis sliding interval | ||
// and the capacity of 32 | ||
slider := equalizer.NewSlider(time.Second, time.Millisecond*100, 32) | ||
|
||
// a Slider with a one-second window size, a 100-millisecond sliding interval, | ||
// and a capacity of 32 | ||
slider := equalizer.NewSlider(time.Second, 100*time.Millisecond, 32) | ||
// non-blocking quota request | ||
haveQuota := slider.Ask() | ||
|
||
haveQuota := slider.TryAcquire() | ||
// blocking call | ||
slider.Take() | ||
slider.Acquire(context.Background()) | ||
``` | ||
|
||
### Benchmarks | ||
```sh | ||
BenchmarkSliderShortWindow-16 123488035 9.67 ns/op 0 B/op 0 allocs/op | ||
BenchmarkSliderLongerWindow-16 128023276 9.76 ns/op 0 B/op 0 allocs/op | ||
```console | ||
BenchmarkSlider_TryAcquire-16 293645348 4.033 ns/op 0 B/op 0 allocs/op | ||
BenchmarkRateLimiter_Allow-16 9362382 127.4 ns/op 0 B/op 0 allocs/op | ||
``` | ||
<sup>*</sup> Compared to `rate.Limiter` from the [golang.org/x/time](https://pkg.go.dev/golang.org/x/time/rate) package. | ||
|
||
## TokenBucket | ||
`TokenBucket` rate limiter is based on the token bucket algorithm with a refill interval. | ||
Implements the `Limiter` interface. | ||
## Token Bucket | ||
`TokenBucket` maintains a fixed number of tokens. Each token represents a request that can be processed. | ||
When a request is made, the rate limiter checks to see if there are any available tokens. If there are, | ||
the request is processed and one token is removed from the bucket. If there are no available tokens, | ||
the request is blocked until a token becomes available. | ||
Implements the `equalizer.Limiter` interface. | ||
|
||
### Usage | ||
### Usage Example | ||
```go | ||
// a TokenBucket with the capacity of 32 and 100 millis refill interval | ||
tokenBucket := equalizer.NewTokenBucket(32, time.Millisecond*100) | ||
|
||
// a TokenBucket with the capacity of 32 and a 100-millisecond refill interval | ||
tokenBucket := equalizer.NewTokenBucket(32, 100*time.Millisecond) | ||
// non-blocking quota request | ||
haveQuota := tokenBucket.Ask() | ||
|
||
haveQuota := tokenBucket.TryAcquire() | ||
// blocking call | ||
tokenBucket.Take() | ||
tokenBucket.Acquire(context.Background()) | ||
``` | ||
|
||
### Benchmarks | ||
```sh | ||
BenchmarkTokenBucketDenseRefill-16 212631714 5.64 ns/op 0 B/op 0 allocs/op | ||
BenchmarkTokenBucketSparseRefill-16 211491368 5.63 ns/op 0 B/op 0 allocs/op | ||
```console | ||
BenchmarkTokenBucket_TryAcquire-16 304653043 3.909 ns/op 0 B/op 0 allocs/op | ||
BenchmarkRateLimiter_Allow-16 9362382 127.4 ns/op 0 B/op 0 allocs/op | ||
``` | ||
<sup>*</sup> Compared to `rate.Limiter` from the [golang.org/x/time](https://pkg.go.dev/golang.org/x/time/rate) package. | ||
|
||
## License | ||
Licensed under the MIT License. | ||
Licensed under the [MIT](./LICENSE) License. |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.