mirror of
https://github.com/hanzoai/ingress.git
synced 2026-10-26 02:47:15 +00:00
hanzokv/go v9.22.0 renames its Go package from `redis` to `kv`; the import
path is unchanged. Update the call sites and rename the middleware's own
client vocabulary to match:
redis_limiter.go -> kv_limiter.go
redisLimiter -> kvLimiter
newRedisLimiter -> newKVLimiter
redisPrefix -> kvPrefix (key prefix value "rate:" is unchanged)
Rediser -> KVClient
mockRedisClient -> mockKVClient
Three things deliberately keep the redis name because they are not ours
to rename:
- `redis.call(...)` inside AllowTokenBucketRaw, and the matching
state.SetGlobal("redis", mod) in the test's Lua VM. That is the KV
server's scripting API — a wire contract, not vocabulary.
- dynamic.Redis / config.Redis. That field is CRD schema: it has
generated deepcopy and applyconfiguration code and it is what a
Middleware CR spells today. Renaming it breaks every deployed CR and
needs a codegen pass, so it belongs in its own change.
- pkg/provider/kv/redis rides github.com/kvtools/redis, a foreign
client, and never touched hanzokv/go.
Verified with go vet ./pkg/middlewares/ratelimiter/... (clean) and
CGO_ENABLED=0 go test ./pkg/middlewares/ratelimiter/... (ok, 121s). A
full `go build ./...` cannot run on darwin/arm64 here: luxfi/accel's cgo
fails with 'stdlib.h' file not found, and linking the test binary fails
with ld: library 'resolv' not found. Both are local toolchain gaps that
predate this change.
Co-authored-by: Hanzo Dev <[email protected]>
67 lines
1.7 KiB
Go
67 lines
1.7 KiB
Go
package ratelimiter
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/hanzokv/go/v9"
|
|
)
|
|
|
|
type KVClient interface {
|
|
Eval(ctx context.Context, script string, keys []string, args ...any) *kv.Cmd
|
|
EvalSha(ctx context.Context, sha1 string, keys []string, args ...any) *kv.Cmd
|
|
ScriptExists(ctx context.Context, hashes ...string) *kv.BoolSliceCmd
|
|
ScriptLoad(ctx context.Context, script string) *kv.StringCmd
|
|
Del(ctx context.Context, keys ...string) *kv.IntCmd
|
|
|
|
EvalRO(ctx context.Context, script string, keys []string, args ...any) *kv.Cmd
|
|
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...any) *kv.Cmd
|
|
}
|
|
|
|
//nolint:dupword
|
|
var AllowTokenBucketRaw = `
|
|
local key = KEYS[1]
|
|
local limit, burst, ttl, t, max_delay = tonumber(ARGV[1]), tonumber(ARGV[2]), tonumber(ARGV[3]), tonumber(ARGV[4]),
|
|
tonumber(ARGV[5])
|
|
|
|
local bucket = {
|
|
limit = limit,
|
|
burst = burst,
|
|
tokens = 0,
|
|
last = 0
|
|
}
|
|
|
|
local rl_source = redis.call('hgetall', key)
|
|
|
|
if table.maxn(rl_source) == 4 then
|
|
-- Get bucket state from redis
|
|
bucket.last = tonumber(rl_source[2])
|
|
bucket.tokens = tonumber(rl_source[4])
|
|
end
|
|
|
|
local last = bucket.last
|
|
if t < last then
|
|
last = t
|
|
end
|
|
|
|
local elapsed = t - last
|
|
local delta = bucket.limit * elapsed
|
|
local tokens = bucket.tokens + delta
|
|
tokens = math.min(tokens, bucket.burst)
|
|
tokens = tokens - 1
|
|
|
|
local wait_duration = 0
|
|
if tokens < 0 then
|
|
wait_duration = (tokens * -1) / bucket.limit
|
|
if wait_duration > max_delay then
|
|
tokens = tokens + 1
|
|
tokens = math.min(tokens, burst)
|
|
end
|
|
end
|
|
|
|
redis.call('hset', key, 'last', t, 'tokens', tokens)
|
|
redis.call('expire', key, ttl)
|
|
|
|
return {tostring(true), tostring(wait_duration),tostring(tokens)}`
|
|
|
|
var AllowTokenBucketScript = kv.NewScript(AllowTokenBucketRaw)
|