Skip to content

Commit

Permalink
Reset rate limiter (#2)
Browse files Browse the repository at this point in the history
* Implementing 'Reset' method for rate limiter
  • Loading branch information
grzegorzkurtyka authored May 26, 2020
1 parent 2039d67 commit 13a8e20
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 8 deletions.
5 changes: 5 additions & 0 deletions gcra.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ type gcra struct {
rdb rediser
}

func (c *gcra) Reset() error {
res := c.rdb.Del(c.key)
return res.Err()
}

// Allow is shorthand for AllowN(key, 1).
func (c *gcra) Allow() (*Result, error) {
return c.AllowN(1)
Expand Down
37 changes: 29 additions & 8 deletions rate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var (
type (
Algorithm interface {
Allow() (*Result, error)
Reset() error
SetKey(string)
}

Expand All @@ -35,6 +36,7 @@ type (
EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd
ScriptExists(hashes ...string) *redis.BoolSliceCmd
ScriptLoad(script string) *redis.StringCmd
Del(key ...string) *redis.IntCmd
}

Limit struct {
Expand Down Expand Up @@ -90,14 +92,9 @@ func NewLimiter(rdb rediser) *Limiter {

func (l *Limiter) Allow(key string, limit *Limit) (*Result, error) {
var algo Algorithm

switch limit.Algorithm {
case SlidingWindowAlgorithm:
algo = &slidingWindow{limit: limit, rdb: l.rdb}
case GCRAAlgorithm:
algo = &gcra{limit: limit, rdb: l.rdb}
default:
return nil, errors.New("algorithm is not supported")
algo, err := l.getAlgorithm(limit)
if err != nil {
return nil, err
}

name, _ := GetAlgorithmName(limit.Algorithm)
Expand All @@ -107,6 +104,30 @@ func (l *Limiter) Allow(key string, limit *Limit) (*Result, error) {
return algo.Allow()
}

func (l *Limiter) Reset(key string, limit *Limit) error {
var algo Algorithm
algo, err := l.getAlgorithm(limit)
if err != nil {
return err
}

name, _ := GetAlgorithmName(limit.Algorithm)

algo.SetKey(l.Prefix + ":" + name + ":" + key)
return algo.Reset()
}

func (l *Limiter) getAlgorithm(limit *Limit) (Algorithm, error) {
switch limit.Algorithm {
case SlidingWindowAlgorithm:
return &slidingWindow{limit: limit, rdb: l.rdb}, nil
case GCRAAlgorithm:
return &gcra{limit: limit, rdb: l.rdb}, nil
default:
return nil, errors.New("algorithm is not supported")
}
}

func GetAlgorithmName(a uint) (string, bool) {
if name, ok := algorithmNames[a]; ok {
return name, ok
Expand Down
48 changes: 48 additions & 0 deletions rate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,54 @@ func TestLimiter_Allow(t *testing.T) {
})
}

func TestLimiter_Reset(t *testing.T) {
l := rateLimiter()

limit := &Limit{
Rate: 1,
Period: time.Minute,
Burst: 1,
}

t.Run("reset-sliding-window", func(t *testing.T) {
limit.Algorithm = SlidingWindowAlgorithm

res, err := l.Allow("sliding-reset_me", limit)
assert.Nil(t, err)
assert.True(t, res.Allowed)

res, err = l.Allow("sliding-reset_me", limit)
assert.Nil(t, err)
assert.False(t, res.Allowed)

err = l.Reset("sliding-reset_me", limit)
assert.Nil(t, err)

res, err = l.Allow("sliding-reset_me", limit)
assert.Nil(t, err)
assert.True(t, res.Allowed)
})

t.Run("reset-gcra-window", func(t *testing.T) {
limit.Algorithm = GCRAAlgorithm

res, err := l.Allow("gcra-reset_me", limit)
assert.Nil(t, err)
assert.True(t, res.Allowed)

res, err = l.Allow("gcra-reset_me", limit)
assert.Nil(t, err)
assert.False(t, res.Allowed)

err = l.Reset("gcra-reset_me", limit)
assert.Nil(t, err)

res, err = l.Allow("gcra-reset_me", limit)
assert.Nil(t, err)
assert.True(t, res.Allowed)
})
}

func BenchmarkAllow_Simple(b *testing.B) {
l := rateLimiter()
limit := &Limit{
Expand Down
5 changes: 5 additions & 0 deletions sliding_window.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ type slidingWindow struct {
rdb rediser
}

func (c *slidingWindow) Reset() error {
res := c.rdb.Del(c.key)
return res.Err()
}

func (c *slidingWindow) SetKey(key string) {
c.key = key
}
Expand Down

0 comments on commit 13a8e20

Please sign in to comment.