mirror of
https://github.com/hanzokv/go.git
synced 2026-09-24 00:31:51 +00:00
We do not use Redis. The client was a go-redis fork and still said so
everywhere: `package redis`, `redis.NewClient`, `redis://`, `extra/redisotel`.
Consumers wrote `redis.Client` against a Valkey-backed store called KV.
package redis -> package kv (93 decls)
redis.X -> kv.X (2,794 call sites)
"redis: …" errors -> "kv: …" (206)
extra/redis{otel,cmd,prometheus,census} -> extra/kv{otel,cmd,prometheus,census}
redis:// , rediss:// -> kv:// , kvs:// (ParseURL)
Redis*/*Redis* idents -> KV*/*KV*
REDIS_VERSION, REDIS_ENDPOINTS_CONFIG_PATH -> KV_*
I previously argued this rename was unsafe because much of it was "wire
contract". That was wrong, and the categorisation shows why: RESP command names
are GET/SET/HSET — they never contain the word. Of 5,771 occurrences only two
kinds were server-visible at all: the ParseURL scheme (we choose what we pass;
our configs already use kv://) and the CLIENT SETINFO lib-name label, which the
server merely records. Nothing here changes a byte of protocol.
Two things deliberately keep the old spelling:
RediSearch — names a specific external module the FT.* commands map to.
StoreDist — contains the letters by accident (sto-reDis-t), not the word.
Breaking for consumers by design: every import site must move redis.X -> kv.X.
Minor bump, never a major — this module stays v9 forever.
110 lines
2.3 KiB
Go
110 lines
2.3 KiB
Go
package kv
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
func (c *ClusterClient) DBSize(ctx context.Context) *IntCmd {
|
|
cmd := NewIntCmd(ctx, "dbsize")
|
|
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
|
|
var size int64
|
|
err := c.ForEachMaster(ctx, func(ctx context.Context, master *Client) error {
|
|
n, err := master.DBSize(ctx).Result()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
atomic.AddInt64(&size, n)
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
cmd.SetErr(err)
|
|
} else {
|
|
cmd.val = size
|
|
}
|
|
return nil
|
|
})
|
|
return cmd
|
|
}
|
|
|
|
func (c *ClusterClient) ScriptLoad(ctx context.Context, script string) *StringCmd {
|
|
cmd := NewStringCmd(ctx, "script", "load", script)
|
|
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
|
|
var mu sync.Mutex
|
|
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
|
|
val, err := shard.ScriptLoad(ctx, script).Result()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
mu.Lock()
|
|
if cmd.Val() == "" {
|
|
cmd.val = val
|
|
}
|
|
mu.Unlock()
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
cmd.SetErr(err)
|
|
}
|
|
return nil
|
|
})
|
|
return cmd
|
|
}
|
|
|
|
func (c *ClusterClient) ScriptFlush(ctx context.Context) *StatusCmd {
|
|
cmd := NewStatusCmd(ctx, "script", "flush")
|
|
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
|
|
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
|
|
return shard.ScriptFlush(ctx).Err()
|
|
})
|
|
if err != nil {
|
|
cmd.SetErr(err)
|
|
}
|
|
return nil
|
|
})
|
|
return cmd
|
|
}
|
|
|
|
func (c *ClusterClient) ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd {
|
|
args := make([]interface{}, 2+len(hashes))
|
|
args[0] = "script"
|
|
args[1] = "exists"
|
|
for i, hash := range hashes {
|
|
args[2+i] = hash
|
|
}
|
|
cmd := NewBoolSliceCmd(ctx, args...)
|
|
|
|
result := make([]bool, len(hashes))
|
|
for i := range result {
|
|
result[i] = true
|
|
}
|
|
|
|
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
|
|
var mu sync.Mutex
|
|
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
|
|
val, err := shard.ScriptExists(ctx, hashes...).Result()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
mu.Lock()
|
|
for i, v := range val {
|
|
result[i] = result[i] && v
|
|
}
|
|
mu.Unlock()
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
cmd.SetErr(err)
|
|
} else {
|
|
cmd.val = result
|
|
}
|
|
return nil
|
|
})
|
|
return cmd
|
|
}
|