forked from avinassh/ratelimit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathredis_store.go
More file actions
86 lines (72 loc) · 1.77 KB
/
redis_store.go
File metadata and controls
86 lines (72 loc) · 1.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package ratelimit
import (
"time"
"github.com/gomodule/redigo/redis"
)
type RedigoStore struct {
Pool *redis.Pool
Script *redis.Script
}
func newRedisPool(address string) *redis.Pool {
return &redis.Pool{
Dial: func() (redis.Conn, error) {
return redis.Dial(
"tcp",
address,
)
},
}
}
func NewRedigoStore(pool *redis.Pool) RedigoStore {
// we will initialise with the script
conn := pool.Get()
defer conn.Close()
var script = redis.NewScript(1, TokenBucketScript)
err := script.Load(conn)
if err != nil {
panic(err)
}
return RedigoStore{Pool: pool, Script: script}
}
func NewRedigoSWStore(pool *redis.Pool) RedigoStore {
// we will initialise with the script
conn := pool.Get()
defer conn.Close()
var script = redis.NewScript(1, SlidingWindowScript)
err := script.Load(conn)
if err != nil {
panic(err)
}
return RedigoStore{Pool: pool, Script: script}
}
func (s *RedigoStore) inc(key string, rate, windowSize, now int) (map[string]int, error) {
conn := s.Pool.Get()
defer conn.Close()
r, err := redis.IntMap(s.Script.Do(conn, key, rate, windowSize, now))
if err != nil {
return nil, err
}
return r, nil
}
func (s *RedigoStore) Inc(key string, rate, windowSize, now int) (StoreResponse, error) {
return buildStoreResponse(s.inc(key, rate, windowSize, now))
}
func buildStoreResponse(result map[string]int, err error) (StoreResponse, error) {
if err != nil {
return StoreResponse{}, err
}
response := StoreResponse{
Counter: result["c"],
LastRefill: MillisToTime(int64(result["ts"])),
}
if result["s"] == 1 {
response.Allowed = true
}
return response, nil
}
func TimeMillis(t time.Time) int64 {
return t.UnixNano() / int64(time.Millisecond)
}
func MillisToTime(m int64) time.Time {
return time.Unix(0, m*int64(time.Millisecond))
}