Skip to content

Commit 0be0611

Browse files
committed
Fix delete key endpoint
1 parent 46bbb07 commit 0be0611

5 files changed

Lines changed: 36 additions & 16 deletions

File tree

pkg/http_server/handlers.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ type (
1818
)
1919

2020
func (h *Handler) Reduce(ctx context.Context, input *ReduceRequest) (*ReduceResponse, error) {
21-
key := input.Key
22-
2321
val, err := h.RateLimiter.Reduce(
24-
key, input.MaxTokens, input.RefillTime, input.RefillAmount, input.Tokens,
22+
input.Key, input.MaxTokens, input.RefillTime, input.RefillAmount, input.Tokens,
2523
)
2624

2725
if err != nil {
@@ -40,9 +38,9 @@ func (h *Handler) Reduce(ctx context.Context, input *ReduceRequest) (*ReduceResp
4038
}
4139

4240
func (h *Handler) Remove(ctx context.Context, input *RemoveRequest) (*RemoveResponse, error) {
43-
key := input.Key
44-
45-
h.RateLimiter.Remove(key)
41+
h.RateLimiter.Remove(
42+
input.Key, input.MaxTokens, input.RefillTime, input.RefillAmount,
43+
)
4644

4745
res := &RemoveResponse{Status: http.StatusOK}
4846
res.Body.Status = "OK"

pkg/http_server/http_server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func (h *Handler) RegisterRoutes(api huma.API) {
9696
huma.Operation{
9797
OperationID: "rate-limiter-delete",
9898
Method: http.MethodDelete,
99-
Path: "/API/v1/rate-limiters/{key}",
99+
Path: "/API/v1/rate-limiters/{key}/{max_tokens}/{refill_time}/{refill_amount}/",
100100
Summary: "Delete the key",
101101
Description: "Delete the key from the rate limiter",
102102
Tags: []string{"Rate Limiter"},
@@ -108,7 +108,7 @@ func (h *Handler) RegisterRoutes(api huma.API) {
108108
huma.Operation{
109109
OperationID: "rate-limiter-get-stats",
110110
Method: http.MethodGet,
111-
Path: "/API/v1/rate-limiters/stats",
111+
Path: "/API/v1/rate-limiters/stats/",
112112
Summary: "Stats of the rate limiter",
113113
Description: "Return the stats of the rate limiter service",
114114
Tags: []string{"Rate Limiter"},

pkg/http_server/schemas.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ type ReduceResponse struct {
2020
}
2121

2222
type RemoveRequest struct {
23-
Key string `path:"key" maxLength:"1024" example:"user:1" doc:"Key for the lock"`
23+
Key string `path:"key" maxLength:"1024" example:"user:1" doc:"Key for the lock"`
24+
MaxTokens int64 `path:"max_tokens" minimum:"1" example:"1000" doc:"Maximum number of tokens in the bucket"`
25+
RefillTime int64 `path:"refill_time" minimum:"1" example:"60" doc:"Time in seconds to refill the bucket"`
26+
RefillAmount int64 `path:"refill_amount" minimum:"1" example:"100" doc:"Number of tokens to refill the bucket"`
2427
}
2528

2629
type RemoveResponse struct {

pkg/limiter/limiter.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ func (l *RateLimiter) GetShard(key int64) *Shard {
5151
return l.shards[uint64(key)%SHARDS]
5252
}
5353

54-
func (l *RateLimiter) Reduce(key string, maxTokens int64, refillTime int64, refillAmount int64, tokens int64) (int64, error) {
55-
defer TimeTrack(time.Now(), "RateLimiter.Reduce")
54+
func (l *RateLimiter) getKey(key string, maxTokens int64, refillTime int64, refillAmount int64) string {
55+
return fmt.Sprintf("%s:%d:%d:%d", key, maxTokens, refillTime, refillAmount)
56+
}
5657

57-
key = fmt.Sprintf("%s:%d:%d:%d", key, maxTokens, refillTime, refillAmount)
58+
func (l *RateLimiter) Reduce(key string, maxTokens int64, refillTime int64, refillAmount int64, tokens int64) (int64, error) {
59+
key = l.getKey(key, maxTokens, refillTime, refillAmount)
5860

5961
h := int64(hash(key))
6062

@@ -67,8 +69,6 @@ func (l *RateLimiter) Reduce(key string, maxTokens int64, refillTime int64, refi
6769

6870
now := time.Now().Unix()
6971

70-
log.Debug().Msgf("Bucket for key: %s found: %t now %d: %+v", key, ok, now, bucket)
71-
7272
if !ok {
7373
value := maxTokens - tokens
7474
tokensNeeded := maxTokens - value
@@ -119,7 +119,6 @@ func (l *RateLimiter) Len() int64 {
119119
}
120120

121121
func (l *RateLimiter) CleanUpFullBuckets() {
122-
123122
for _, shard := range l.shards {
124123
shard.mu.Lock()
125124
for key, bucket := range shard.Buckets {
@@ -143,7 +142,9 @@ func (l *RateLimiter) StartCleanUpFullBuckets() {
143142
}
144143
}
145144

146-
func (l *RateLimiter) Remove(key string) {
145+
func (l *RateLimiter) Remove(key string, maxTokens int64, refillTime int64, refillAmount int64) {
146+
key = l.getKey(key, maxTokens, refillTime, refillAmount)
147+
147148
h := int64(hash(key))
148149
shard := l.GetShard(h)
149150

pkg/limiter/limiter_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,24 @@ func TestRateLimiterWithManyKeys(t *testing.T) {
7474
}
7575
}
7676

77+
func TestRateLimiterReuseTheSameKey(t *testing.T) {
78+
79+
rl := NewRateLimiter()
80+
81+
val, _ := rl.Reduce("user:123", 1000, 1, 50, 1)
82+
assert.Equal(t, int64(999), val)
83+
val, _ = rl.Reduce("user:123", 1000, 1, 50, 1)
84+
assert.Equal(t, int64(998), val)
85+
val, _ = rl.Reduce("user:123", 1000, 1, 50, 1)
86+
assert.Equal(t, int64(997), val)
87+
88+
val, _ = rl.Reduce("user:123", 50, 1, 50, 1)
89+
assert.Equal(t, int64(49), val)
90+
91+
val, _ = rl.Reduce("user:123", 1000, 1, 50, 1)
92+
assert.Equal(t, int64(996), val)
93+
}
94+
7795
func TestRateLimiterD(t *testing.T) {
7896
rl := NewRateLimiter()
7997

0 commit comments

Comments
 (0)