Skip to content

Commit 98dbfac

Browse files
committed
Implement redisstore
1 parent 138be49 commit 98dbfac

1 file changed

Lines changed: 51 additions & 1 deletion

File tree

internal/store/redis.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,51 @@
1-
// internal/store/redis.go
1+
package store
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"github.com/redis/go-redis/v9"
8+
"github.com/Pavan-Rana/redis-rate-limiter/internal/limiter"
9+
)
10+
11+
type RedisStore struct {
12+
client *redis.Client
13+
scripts *LuaScripts
14+
}
15+
16+
func NewRedisStore(addr string) (*RedisStore, error) {
17+
client := redis.NewClient(&redis.Options{Addr: addr})
18+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
19+
defer cancel()
20+
21+
if err := client.Ping(ctx).Err(); err != nil {
22+
return nil, err
23+
}
24+
25+
scripts, err := LoadScripts(ctx, client)
26+
if err != nil {
27+
return nil, err
28+
}
29+
30+
return &RedisStore{client: client, scripts: scripts}, nil
31+
}
32+
33+
// Single round-trip; no TOCTOU race possible across replicas.
34+
func (r *RedisStore) AllowRequest(ctx context.Context, key string, policy limiter.Policy) (bool, error) {
35+
nowMs := time.Now().UnixMilli()
36+
windowMs := policy.Window.Milliseconds()
37+
38+
result, err := r.client.EvalSha(ctx, r.scripts.SlidingWindowSHA, []string{key},
39+
nowMs, windowMs, policy.Limit
40+
).Int()
41+
42+
if err != nil {
43+
return false, err
44+
}
45+
46+
return result == 1, nil
47+
}
48+
49+
func (r *RedisStore) Ping(ctx context.Context) error {
50+
return r.client.Ping(ctx).Err()
51+
}

0 commit comments

Comments
 (0)