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.
67 lines
1.2 KiB
Go
67 lines
1.2 KiB
Go
package kv
|
|
|
|
import (
|
|
"context"
|
|
)
|
|
|
|
// ScanIterator is used to incrementally iterate over a collection of elements.
|
|
type ScanIterator struct {
|
|
cmd *ScanCmd
|
|
pos int
|
|
}
|
|
|
|
// Err returns the last iterator error, if any.
|
|
func (it *ScanIterator) Err() error {
|
|
return it.cmd.Err()
|
|
}
|
|
|
|
// Next advances the cursor and returns true if more values can be read.
|
|
func (it *ScanIterator) Next(ctx context.Context) bool {
|
|
// Instantly return on errors.
|
|
if it.cmd.Err() != nil {
|
|
return false
|
|
}
|
|
|
|
// Advance cursor, check if we are still within range.
|
|
if it.pos < len(it.cmd.page) {
|
|
it.pos++
|
|
return true
|
|
}
|
|
|
|
for {
|
|
// Return if there is no more data to fetch.
|
|
if it.cmd.cursor == 0 {
|
|
return false
|
|
}
|
|
|
|
// Fetch next page.
|
|
switch it.cmd.args[0] {
|
|
case "scan", "qscan":
|
|
it.cmd.args[1] = it.cmd.cursor
|
|
default:
|
|
it.cmd.args[2] = it.cmd.cursor
|
|
}
|
|
|
|
err := it.cmd.process(ctx, it.cmd)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
it.pos = 1
|
|
|
|
// KV can occasionally return empty page.
|
|
if len(it.cmd.page) > 0 {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
// Val returns the key/field at the current cursor position.
|
|
func (it *ScanIterator) Val() string {
|
|
var v string
|
|
if it.cmd.Err() == nil && it.pos > 0 && it.pos <= len(it.cmd.page) {
|
|
v = it.cmd.page[it.pos-1]
|
|
}
|
|
return v
|
|
}
|