diff --git a/README.md b/README.md index 050f0bb..3e51de4 100644 --- a/README.md +++ b/README.md @@ -64,31 +64,31 @@ Optional: `-gossip-secret `. ### CLI (`sc`) ```bash -# With supercache-node running on defaults (-demo-keyspace: demo + tags + board + profile + doc + flags + embeddings): +# With supercache-node running on defaults (keyspace name = lowercase mode): go run ./cmd/sc put greeting "hello" go run ./cmd/sc get greeting go run ./cmd/sc del greeting -go run ./cmd/sc -keyspace tags sadd features dark_mode -go run ./cmd/sc -keyspace tags sismember features dark_mode -go run ./cmd/sc -keyspace board zadd lb 100 alice -go run ./cmd/sc -keyspace board zrange lb 0 -1 +go run ./cmd/sc -keyspace set sadd features dark_mode +go run ./cmd/sc -keyspace set sismember features dark_mode +go run ./cmd/sc -keyspace zset zadd lb 100 alice +go run ./cmd/sc -keyspace zset zrange lb 0 -1 go run ./cmd/sc -keyspace places geoadd city -74 40.7 shop go run ./cmd/sc -keyspace places georadius city -74 40.7 20000 10 go run ./cmd/sc -keyspace inbox rpush q event1 go run ./cmd/sc -keyspace inbox lrange q 0 -1 -go run ./cmd/sc -keyspace profile hset user email a@b -go run ./cmd/sc -keyspace profile hgetall user +go run ./cmd/sc -keyspace hash hset user email a@b +go run ./cmd/sc -keyspace hash hgetall user # ModeCounter (register a ModeCounter keyspace; not in -demo-keyspace): # go run ./cmd/sc -keyspace rl incr alice:1 -go run ./cmd/sc -keyspace doc jsonset user $.name '"Ada"' -go run ./cmd/sc -keyspace doc jsonget user $.name -go run ./cmd/sc -keyspace flags bitset seen 0 1 -go run ./cmd/sc -keyspace flags bitget seen 0 -go run ./cmd/sc -keyspace embeddings vadd products east 1,0 -go run ./cmd/sc -keyspace embeddings vadd products north 0,1 -go run ./cmd/sc -keyspace embeddings vadd products ne 0.7,0.7 -go run ./cmd/sc -keyspace embeddings vcard products -go run ./cmd/sc -keyspace embeddings vsim products 1,0.05 3 +go run ./cmd/sc -keyspace json jsonset user $.name '"Ada"' +go run ./cmd/sc -keyspace json jsonget user $.name +go run ./cmd/sc -keyspace bitmap bitset seen 0 1 +go run ./cmd/sc -keyspace bitmap bitget seen 0 +go run ./cmd/sc -keyspace vectorset vadd products east 1,0 +go run ./cmd/sc -keyspace vectorset vadd products north 0,1 +go run ./cmd/sc -keyspace vectorset vadd products ne 0.7,0.7 +go run ./cmd/sc -keyspace vectorset vcard products +go run ./cmd/sc -keyspace vectorset vsim products 1,0.05 3 go run ./cmd/sc -keyspace seen bloom add users alice # ModeBloom keyspace # ModeTopK (register a ModeTopK keyspace, or use examples/billboard plays/hot): # go run ./cmd/sc -keyspace plays topkadd hot t001 @@ -140,7 +140,7 @@ See [examples/billboard/README.md](./examples/billboard/README.md). Official cha go run ./examples/hash # 3-node in-process walkthrough (HSet/HGet/HDel, concurrent fields) ``` -See [examples/hash/README.md](./examples/hash/README.md). `sc -keyspace profile` talks to the node demo keyspace. +See [examples/hash/README.md](./examples/hash/README.md). `sc -keyspace hash` talks to the node demo keyspace. ### ModeCounter rate limiter @@ -156,7 +156,7 @@ See [examples/ratelimit/README.md](./examples/ratelimit/README.md). go run ./examples/json # 3-node in-process walkthrough (path set/get/del) ``` -See [examples/json/README.md](./examples/json/README.md). `sc -keyspace doc` talks to the node demo keyspace. +See [examples/json/README.md](./examples/json/README.md). `sc -keyspace json` talks to the node demo keyspace. ### ModeBitmap packed bits @@ -164,7 +164,7 @@ See [examples/json/README.md](./examples/json/README.md). `sc -keyspace doc` tal go run ./examples/bitmap # 3-node in-process walkthrough (BitSet/BitGet/BitCount/BitPos) ``` -See [examples/bitmap/README.md](./examples/bitmap/README.md). `sc -keyspace flags` talks to the node demo keyspace. +See [examples/bitmap/README.md](./examples/bitmap/README.md). `sc -keyspace bitmap` talks to the node demo keyspace. ### ModeHLL approximate distinct count @@ -213,7 +213,7 @@ Apps: `client.DialTLS` with `pkg/tlsconfig.ClientFiles`. See [docs/OPERATIONS.md | `pkg/warmup` | Hot keys, topology handoff (hot then rest), refresh-ahead | | `pkg/client` | Application gRPC client (KV + Bloom + Set + ZSet + Geo + List + Hash + Counter + JSON + Bitmap + HLL + TopK) | | `pkg/tlsconfig` | TLS/mTLS config from PEM files | -| `cmd/supercache-node` | Node binary (`-demo-keyspace`: demo / tags / board / profile / doc / flags / embeddings) | +| `cmd/supercache-node` | Node binary (`-demo-keyspace`: cacheonly / set / zset / hash / json / bitmap / vectorset) | | `cmd/sc` | CLI: get/put/del, bloom, sadd*, z*, geo*, l*, h*, incr/cget, json*, bit*, hlladd/hllcount, topkadd/topklist, admin diagnostics | | `cmd/scbench` | SuperCache vs Redis load harness + in-process matrix | diff --git a/cmd/sc/main.go b/cmd/sc/main.go index 1e9d347..93a6db9 100644 --- a/cmd/sc/main.go +++ b/cmd/sc/main.go @@ -38,7 +38,7 @@ func run(args []string) int { var ( addr = fs.String("addr", envOr("SC_ADDR", "127.0.0.1:9000"), "cache gRPC seed(s), comma-separated (app port, not peer)") admin = fs.String("admin", envOr("SC_ADMIN", "127.0.0.1:8080"), "admin HTTP seed(s), comma-separated") - keyspace = fs.String("keyspace", envOr("SC_KEYSPACE", "demo"), "default keyspace") + keyspace = fs.String("keyspace", envOr("SC_KEYSPACE", "cacheonly"), "default keyspace") timeout = fs.Duration("timeout", 5*time.Second, "per-request timeout") ttl = fs.Duration("ttl", 0, "TTL for put (0 + -no-expiry = never expire)") noExpiry = fs.Bool("no-expiry", false, "put with TTL=0 (no expiry)") @@ -382,16 +382,16 @@ Environment: SC_ADDR, SC_ADMIN, SC_KEYSPACE, SC_TLS_CA, SC_TLS_CERT, SC_TLS_KEY, Examples: sc put greeting "hello world" sc get greeting - sc -keyspace tags sadd features dark_mode - sc -keyspace tags sismember features dark_mode - sc -keyspace board zadd lb 100 alice - sc -keyspace board zrange lb 0 -1 + sc -keyspace set sadd features dark_mode + sc -keyspace set sismember features dark_mode + sc -keyspace zset zadd lb 100 alice + sc -keyspace zset zrange lb 0 -1 sc -addr 127.0.0.1:9000,127.0.0.1:9010,127.0.0.1:9020 ping sc -admin 127.0.0.1:8081,127.0.0.1:8082 peers sc # REPL sc> put k v sc> get k - sc> keyspace demo + sc> keyspace cacheonly sc> quit `) } diff --git a/cmd/scbench/README.md b/cmd/scbench/README.md index be1f88c..9d0718d 100644 --- a/cmd/scbench/README.md +++ b/cmd/scbench/README.md @@ -36,7 +36,7 @@ Do **not** compare 3-node SuperCache to 1 Redis and call it “faster.” # Prefer native Redis for fairness redis-server --port 6379 --save "" --appendonly no -# SuperCache (demo keyspace = CacheOnly "demo") +# SuperCache (demo keyspace = CacheOnly "cacheonly") go run ./cmd/supercache-node \ -cache 127.0.0.1:9000 -peer 127.0.0.1:9001 -admin 127.0.0.1:8080 ``` diff --git a/cmd/scbench/main.go b/cmd/scbench/main.go index 3cbe1d4..f09e4ec 100644 --- a/cmd/scbench/main.go +++ b/cmd/scbench/main.go @@ -42,7 +42,7 @@ func main() { warmup = flag.Duration("warmup", 5*time.Second, "warmup before each trial (discarded)") trials = flag.Int("trials", 5, "independent measure trials; report median") readRatio = flag.Float64("read-ratio", 0.95, "GET fraction in mixed mode") - keyspace = flag.String("keyspace", "demo", "SuperCache keyspace") + keyspace = flag.String("keyspace", "cacheonly", "SuperCache keyspace") prefix = flag.String("prefix", "scbench:", "key prefix") prefill = flag.Bool("prefill", true, "prefill before get/mixed") dist = flag.String("dist", "uniform", "uniform | zipf") diff --git a/cmd/supercache-node/main.go b/cmd/supercache-node/main.go index 47c60a9..d065a46 100644 --- a/cmd/supercache-node/main.go +++ b/cmd/supercache-node/main.go @@ -44,7 +44,7 @@ func main() { gossipAdv = flag.String("gossip-advertise", "127.0.0.1", "gossip advertise address") seeds = flag.String("seeds", "", "comma-separated gossip seeds host:port") gossipSecret = flag.String("gossip-secret", "", "optional gossip shared secret") - demoKS = flag.Bool("demo-keyspace", true, "register stock demo keyspaces (demo/tags/board/profile/doc/flags/embeddings)") + demoKS = flag.Bool("demo-keyspace", true, "register stock demo keyspaces named after the mode (cacheonly/set/zset/hash/json/bitmap/vectorset)") globalRPS = flag.Float64("global-rps", 0, "global DataSource rate limit (0=off)") cluster = flag.Bool("cluster", false, "enable gossip membership + peer fan-out") showVersion = flag.Bool("version", false, "print version and exit") @@ -90,7 +90,7 @@ func main() { if err := registerDemoKeyspaces(eng); err != nil { log.Fatal(err) } - log.Printf("demo keyspaces: demo=CacheOnly tags=ModeSet board=ModeZSet profile=ModeHash doc=ModeJSON flags=ModeBitmap embeddings=ModeVectorSet") + log.Printf("demo keyspaces: %s", strings.Join(demoKeyspaceNames(), " ")) } cacheSrvOpts, peerSrvOpts, peerDialTLS, err := buildTLS( @@ -285,21 +285,36 @@ func buildTLS( return cacheOpts, peerOpts, peerDial, nil } +// demoKeyspaceName is lowercase Mode.String() so sc -keyspace is guessable. +func demoKeyspaceName(m keyspace.Mode) string { + return strings.ToLower(m.String()) +} + +func demoKeyspaceNames() []string { + var out []string + for _, cfg := range demoKeyspaceConfigs() { + out = append(out, cfg.Name+"="+cfg.Mode.String()) + } + return out +} + +func demoKeyspaceConfigs() []keyspace.Config { + ttl := 30 * time.Minute + return []keyspace.Config{ + {Name: demoKeyspaceName(keyspace.ModeCacheOnly), Mode: keyspace.ModeCacheOnly, MaxBytes: 64 << 20, TTL: 5 * time.Minute}, + {Name: demoKeyspaceName(keyspace.ModeSet), Mode: keyspace.ModeSet, MaxBytes: 16 << 20, TTL: ttl}, + {Name: demoKeyspaceName(keyspace.ModeZSet), Mode: keyspace.ModeZSet, MaxBytes: 16 << 20, TTL: ttl}, + {Name: demoKeyspaceName(keyspace.ModeHash), Mode: keyspace.ModeHash, MaxBytes: 16 << 20, TTL: ttl}, + {Name: demoKeyspaceName(keyspace.ModeJSON), Mode: keyspace.ModeJSON, MaxBytes: 16 << 20, TTL: ttl}, + {Name: demoKeyspaceName(keyspace.ModeBitmap), Mode: keyspace.ModeBitmap, MaxBytes: 16 << 20, TTL: ttl}, + {Name: demoKeyspaceName(keyspace.ModeVectorSet), Mode: keyspace.ModeVectorSet, MaxBytes: 16 << 20, TTL: ttl}, + } +} + // registerDemoKeyspaces installs the stock -demo-keyspace set. func registerDemoKeyspaces(eng *engine.Engine) error { - type ks struct { - cfg keyspace.Config - } - for _, item := range []ks{ - {keyspace.Config{Name: "demo", Mode: keyspace.ModeCacheOnly, MaxBytes: 64 << 20, TTL: 5 * time.Minute}}, - {keyspace.Config{Name: "tags", Mode: keyspace.ModeSet, MaxBytes: 16 << 20, TTL: 30 * time.Minute}}, - {keyspace.Config{Name: "board", Mode: keyspace.ModeZSet, MaxBytes: 16 << 20, TTL: 30 * time.Minute}}, - {keyspace.Config{Name: "profile", Mode: keyspace.ModeHash, MaxBytes: 16 << 20, TTL: 30 * time.Minute}}, - {keyspace.Config{Name: "doc", Mode: keyspace.ModeJSON, MaxBytes: 16 << 20, TTL: 30 * time.Minute}}, - {keyspace.Config{Name: "flags", Mode: keyspace.ModeBitmap, MaxBytes: 16 << 20, TTL: 30 * time.Minute}}, - {keyspace.Config{Name: "embeddings", Mode: keyspace.ModeVectorSet, MaxBytes: 16 << 20, TTL: 30 * time.Minute}}, - } { - if err := eng.UpdateKeySpace(item.cfg); err != nil { + for _, cfg := range demoKeyspaceConfigs() { + if err := eng.UpdateKeySpace(cfg); err != nil { return err } } diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md index e8ce488..251d7ce 100644 --- a/docs/OPERATIONS.md +++ b/docs/OPERATIONS.md @@ -78,7 +78,7 @@ Peer mesh with mTLS: every node uses the same CA; each node presents a cert sign Wrong verb for the mode → invalid argument. Configure the same modes on every node (see rollout above). -Demo node (`-demo-keyspace`): registers `demo` (CacheOnly), `tags` (ModeSet), `board` (ModeZSet), `profile` (ModeHash), `doc` (ModeJSON), `flags` (ModeBitmap), `embeddings` (ModeVectorSet). Geo/List/Counter/HLL/TopK/CMS keyspaces are configured by the app. Live plays billboard: [examples/billboard](../examples/billboard/README.md). Hash walkthrough: [examples/hash](../examples/hash/README.md). Rate limiter: [examples/ratelimit](../examples/ratelimit/README.md). JSON document: [examples/json](../examples/json/README.md). Bitmap flags: [examples/bitmap](../examples/bitmap/README.md). HLL sketch: [examples/hll](../examples/hll/README.md). +Demo node (`-demo-keyspace`): one keyspace per shipped demo mode, **name = lowercase `Mode.String()`** — `cacheonly`, `set`, `zset`, `hash`, `json`, `bitmap`, `vectorset`. Geo/List/Counter/HLL/TopK/CMS are not on the stock node (register them in the app). Live plays billboard: [examples/billboard](../examples/billboard/README.md). Hash walkthrough: [examples/hash](../examples/hash/README.md). Rate limiter: [examples/ratelimit](../examples/ratelimit/README.md). JSON document: [examples/json](../examples/json/README.md). Bitmap flags: [examples/bitmap](../examples/bitmap/README.md). HLL sketch: [examples/hll](../examples/hll/README.md). ## Consistency cheatsheet diff --git a/examples/bitmap/README.md b/examples/bitmap/README.md index 80042a6..4b7b1c9 100644 --- a/examples/bitmap/README.md +++ b/examples/bitmap/README.md @@ -33,7 +33,7 @@ CI covers the same path: `go test ./examples/bitmap`. ## Manual `sc` against a node `supercache-node -demo-keyspace` (the default) now also registers -**`flags`** (`ModeBitmap`). +**`bitmap`** (`ModeBitmap`). `sc bitset` / `bitget` take a numeric offset. The bit token must be `0` or `1`. @@ -43,16 +43,16 @@ go run ./cmd/supercache-node \ -cache 127.0.0.1:9000 -peer 127.0.0.1:9001 -admin 127.0.0.1:8080 # terminal 2 -go run ./cmd/sc -keyspace flags bitset seen 0 1 -go run ./cmd/sc -keyspace flags bitset seen 8 1 -go run ./cmd/sc -keyspace flags bitget seen 0 -go run ./cmd/sc -keyspace flags bitget seen 3 -go run ./cmd/sc -keyspace flags bitcount seen -go run ./cmd/sc -keyspace flags bitcount seen 0 0 -go run ./cmd/sc -keyspace flags bitpos seen 1 -go run ./cmd/sc -keyspace flags bitset seen 0 0 -go run ./cmd/sc -keyspace flags bitcount seen -go run ./cmd/sc -keyspace flags del seen # tombstone whole bitmap +go run ./cmd/sc -keyspace bitmap bitset seen 0 1 +go run ./cmd/sc -keyspace bitmap bitset seen 8 1 +go run ./cmd/sc -keyspace bitmap bitget seen 0 +go run ./cmd/sc -keyspace bitmap bitget seen 3 +go run ./cmd/sc -keyspace bitmap bitcount seen +go run ./cmd/sc -keyspace bitmap bitcount seen 0 0 +go run ./cmd/sc -keyspace bitmap bitpos seen 1 +go run ./cmd/sc -keyspace bitmap bitset seen 0 0 +go run ./cmd/sc -keyspace bitmap bitcount seen +go run ./cmd/sc -keyspace bitmap del seen # tombstone whole bitmap ``` `bitget` of a missing name prints `(nil)` and exits 1. diff --git a/examples/cluster3/README.md b/examples/cluster3/README.md index 7d1f0c8..f11cad3 100644 --- a/examples/cluster3/README.md +++ b/examples/cluster3/README.md @@ -2,7 +2,7 @@ Exercises **CacheOnly** (`demo`: sessions / KV), **ModeSet** (`tags`: feature flags), and **ModeZSet** (`board`: leaderboard via `ZAdd` / `ZScore` / `ZRange` / `ZRem`). -Requires `supercache-node` with `-demo-keyspace` (default), which registers `demo`, `tags`, `board`, `profile`, `doc`, `flags`, and `embeddings` (this example uses the first three). +Requires `supercache-node` with `-demo-keyspace` (default), which registers keyspaces named after the mode (`cacheonly`, `set`, `zset`, `hash`, `json`, `bitmap`, `vectorset`). This example uses `cacheonly`, `set`, and `zset`. Start three nodes (separate terminals), then run this example. diff --git a/examples/cluster3/main.go b/examples/cluster3/main.go index 88b2e75..e869332 100644 --- a/examples/cluster3/main.go +++ b/examples/cluster3/main.go @@ -25,7 +25,7 @@ func main() { } fmt.Println("=== 1) Put session:user1 via n1 (CacheOnly demo) ===") - if err := clients[0].Put(ctx, "demo", "session:user1", + if err := clients[0].Put(ctx, "cacheonly", "session:user1", []byte(`{"user":"alice","role":"admin"}`), client.WithTTL(2*time.Minute)); err != nil { fmt.Println("put err:", err) os.Exit(1) @@ -35,7 +35,7 @@ func main() { fmt.Println("\n=== 2) Get session:user1 from all 3 nodes (fan-out check) ===") for i, c := range clients { - v, err := c.Get(ctx, "demo", "session:user1") + v, err := c.Get(ctx, "cacheonly", "session:user1") if err != nil { fmt.Printf(" n%d ERROR: %v\n", i+1, err) } else { @@ -46,7 +46,7 @@ func main() { fmt.Println("\n=== 3) ModeSet feature flags via n2 (SetAdd into set name features) ===") // Exact membership: one set name, many items — not one KV key per flag. for _, item := range []string{"dark_mode", "beta", "max_cart"} { - if err := clients[1].SetAdd(ctx, "tags", "features", []byte(item)); err != nil { + if err := clients[1].SetAdd(ctx, "set", "features", []byte(item)); err != nil { fmt.Printf(" SetAdd %s err: %v\n", item, err) os.Exit(1) } @@ -56,20 +56,20 @@ func main() { fmt.Println("\n=== 4) SetContains / SetCard / SetMembers from n3 ===") for _, item := range []string{"dark_mode", "beta", "max_cart", "unknown_flag"} { - ok, err := clients[2].SetContains(ctx, "tags", "features", []byte(item)) + ok, err := clients[2].SetContains(ctx, "set", "features", []byte(item)) if err != nil { fmt.Printf(" contains %s ERROR: %v\n", item, err) } else { fmt.Printf(" contains %s = %v\n", item, ok) } } - n, err := clients[2].SetCard(ctx, "tags", "features") + n, err := clients[2].SetCard(ctx, "set", "features") if err != nil { fmt.Println(" card ERROR:", err) } else { fmt.Printf(" SetCard(features) = %d\n", n) } - mem, err := clients[2].SetMembers(ctx, "tags", "features") + mem, err := clients[2].SetMembers(ctx, "set", "features") if err != nil { fmt.Println(" members ERROR:", err) } else { @@ -81,13 +81,13 @@ func main() { } fmt.Println("\n=== 5) SetRemove beta via n1; confirm on n2 ===") - if err := clients[0].SetRemove(ctx, "tags", "features", []byte("beta")); err != nil { + if err := clients[0].SetRemove(ctx, "set", "features", []byte("beta")); err != nil { fmt.Println(" remove err:", err) } else { fmt.Println(" SetRemove beta OK") } time.Sleep(400 * time.Millisecond) - ok, err := clients[1].SetContains(ctx, "tags", "features", []byte("beta")) + ok, err := clients[1].SetContains(ctx, "set", "features", []byte("beta")) fmt.Printf(" n2 contains beta = %v err=%v (expect false)\n", ok, err) fmt.Println("\n=== 6) ModeZSet leaderboard via n2 (ZAdd into board name top_tracks) ===") @@ -100,7 +100,7 @@ func main() { {"carol", 180}, } for _, s := range scores { - if err := clients[1].ZAdd(ctx, "board", "top_tracks", []byte(s.member), s.score); err != nil { + if err := clients[1].ZAdd(ctx, "zset", "top_tracks", []byte(s.member), s.score); err != nil { fmt.Printf(" ZAdd %s err: %v\n", s.member, err) os.Exit(1) } @@ -110,20 +110,20 @@ func main() { fmt.Println("\n=== 7) ZScore / ZCard / ZRange from n3 ===") for _, m := range []string{"alice", "bob", "nobody"} { - sc, ok, err := clients[2].ZScore(ctx, "board", "top_tracks", []byte(m)) + sc, ok, err := clients[2].ZScore(ctx, "zset", "top_tracks", []byte(m)) if err != nil { fmt.Printf(" zscore %s ERROR: %v\n", m, err) } else { fmt.Printf(" zscore %s = %v present=%v\n", m, sc, ok) } } - n, err = clients[2].ZCard(ctx, "board", "top_tracks") + n, err = clients[2].ZCard(ctx, "zset", "top_tracks") if err != nil { fmt.Println(" zcard ERROR:", err) } else { fmt.Printf(" ZCard(top_tracks) = %d\n", n) } - rank, err := clients[2].ZRange(ctx, "board", "top_tracks", 0, -1) + rank, err := clients[2].ZRange(ctx, "zset", "top_tracks", 0, -1) if err != nil { fmt.Println(" zrange ERROR:", err) } else { @@ -133,7 +133,7 @@ func main() { } fmt.Println() } - win, err := clients[2].ZRangeByScore(ctx, "board", "top_tracks", 150, 300) + win, err := clients[2].ZRangeByScore(ctx, "zset", "top_tracks", 150, 300) if err != nil { fmt.Println(" zrangebyscore ERROR:", err) } else { @@ -145,17 +145,17 @@ func main() { } fmt.Println("\n=== 8) ZRem alice via n1; confirm on n2 ===") - if err := clients[0].ZRem(ctx, "board", "top_tracks", []byte("alice")); err != nil { + if err := clients[0].ZRem(ctx, "zset", "top_tracks", []byte("alice")); err != nil { fmt.Println(" zrem err:", err) } else { fmt.Println(" ZRem alice OK") } time.Sleep(400 * time.Millisecond) - _, ok, err = clients[1].ZScore(ctx, "board", "top_tracks", []byte("alice")) + _, ok, err = clients[1].ZScore(ctx, "zset", "top_tracks", []byte("alice")) fmt.Printf(" n2 zscore alice present=%v err=%v (expect false)\n", ok, err) fmt.Println("\n=== 9) Delete session:user1 via n3 ===") - if err := clients[2].Delete(ctx, "demo", "session:user1"); err != nil { + if err := clients[2].Delete(ctx, "cacheonly", "session:user1"); err != nil { fmt.Println(" delete note:", err) } else { fmt.Println(" Delete OK (all peers ACKed)") @@ -164,14 +164,14 @@ func main() { fmt.Println("\n=== 10) Confirm session miss on all nodes ===") for i, c := range clients { - _, err := c.Get(ctx, "demo", "session:user1") + _, err := c.Get(ctx, "cacheonly", "session:user1") fmt.Printf(" n%d: %v\n", i+1, err) } fmt.Println("\n=== 11) Spread 12 KV keys (write rotate, read next node) ===") for i := 0; i < 12; i++ { k := fmt.Sprintf("item:%d", i) - _ = clients[i%3].Put(ctx, "demo", k, []byte(fmt.Sprintf("value-%d", i))) + _ = clients[i%3].Put(ctx, "cacheonly", k, []byte(fmt.Sprintf("value-%d", i))) } time.Sleep(600 * time.Millisecond) hits := 0 @@ -179,7 +179,7 @@ func main() { k := fmt.Sprintf("item:%d", i) want := fmt.Sprintf("value-%d", i) c := clients[(i+1)%3] - if v, err := c.Get(ctx, "demo", k); err == nil && string(v) == want { + if v, err := c.Get(ctx, "cacheonly", k); err == nil && string(v) == want { hits++ } else { fmt.Printf(" lag/miss %s: %v\n", k, err) diff --git a/examples/hash/README.md b/examples/hash/README.md index c8e3e82..cb1b731 100644 --- a/examples/hash/README.md +++ b/examples/hash/README.md @@ -35,7 +35,7 @@ CI covers the same path: `go test ./examples/hash`. ## Manual `sc` against a node `supercache-node -demo-keyspace` (the default) now also registers -**`profile`** (`ModeHash`). +**`hash`** (`ModeHash`). ```bash # terminal 1 @@ -43,18 +43,18 @@ go run ./cmd/supercache-node \ -cache 127.0.0.1:9000 -peer 127.0.0.1:9001 -admin 127.0.0.1:8080 # terminal 2 -go run ./cmd/sc -keyspace profile hset alice email alice@example.com -go run ./cmd/sc -keyspace profile hset alice name Alice -go run ./cmd/sc -keyspace profile hset alice plan pro -go run ./cmd/sc -keyspace profile hget alice email -go run ./cmd/sc -keyspace profile hexists alice plan -go run ./cmd/sc -keyspace profile hlen alice -go run ./cmd/sc -keyspace profile hgetall alice +go run ./cmd/sc -keyspace hash hset alice email alice@example.com +go run ./cmd/sc -keyspace hash hset alice name Alice +go run ./cmd/sc -keyspace hash hset alice plan pro +go run ./cmd/sc -keyspace hash hget alice email +go run ./cmd/sc -keyspace hash hexists alice plan +go run ./cmd/sc -keyspace hash hlen alice +go run ./cmd/sc -keyspace hash hgetall alice # values may contain spaces: -go run ./cmd/sc -keyspace profile hset alice bio writes caches -go run ./cmd/sc -keyspace profile hdel alice plan -go run ./cmd/sc -keyspace profile hlen alice -go run ./cmd/sc -keyspace profile del alice # tombstone whole hash +go run ./cmd/sc -keyspace hash hset alice bio writes caches +go run ./cmd/sc -keyspace hash hdel alice plan +go run ./cmd/sc -keyspace hash hlen alice +go run ./cmd/sc -keyspace hash del alice # tombstone whole hash ``` `hgetall` prints one `fieldvalue` line per pair. `hget` of a missing diff --git a/examples/json/README.md b/examples/json/README.md index b9a7873..033bf68 100644 --- a/examples/json/README.md +++ b/examples/json/README.md @@ -35,7 +35,7 @@ CI covers the same path: `go test ./examples/json`. ## Manual `sc` against a node `supercache-node -demo-keyspace` (the default) now also registers -**`doc`** (`ModeJSON`). +**`json`** (`ModeJSON`). `sc jsonset` joins remaining args like `put` / `hset`. The server rejects non-JSON, so quote string values: @@ -46,14 +46,14 @@ go run ./cmd/supercache-node \ -cache 127.0.0.1:9000 -peer 127.0.0.1:9001 -admin 127.0.0.1:8080 # terminal 2 -go run ./cmd/sc -keyspace doc jsonset user $ '{"name":"Ada","n":1}' -go run ./cmd/sc -keyspace doc jsonset user $.name '"Ada"' -go run ./cmd/sc -keyspace doc jsonset user $.n 1 -go run ./cmd/sc -keyspace doc jsonget user $.n -go run ./cmd/sc -keyspace doc jsonget user -go run ./cmd/sc -keyspace doc jsondel user $.name -go run ./cmd/sc -keyspace doc jsondel user # clear to {} -go run ./cmd/sc -keyspace doc del user # tombstone +go run ./cmd/sc -keyspace json jsonset user $ '{"name":"Ada","n":1}' +go run ./cmd/sc -keyspace json jsonset user $.name '"Ada"' +go run ./cmd/sc -keyspace json jsonset user $.n 1 +go run ./cmd/sc -keyspace json jsonget user $.n +go run ./cmd/sc -keyspace json jsonget user +go run ./cmd/sc -keyspace json jsondel user $.name +go run ./cmd/sc -keyspace json jsondel user # clear to {} +go run ./cmd/sc -keyspace json del user # tombstone ``` `jsonget` of a missing path prints `(nil)` and exits 1. diff --git a/examples/vecset/README.md b/examples/vecset/README.md index 98de5de..776861c 100644 --- a/examples/vecset/README.md +++ b/examples/vecset/README.md @@ -30,7 +30,7 @@ CI covers the same path: `go test ./examples/vecset`. ## Manual `sc` against a stock node -`supercache-node -demo-keyspace` (the default) registers **`embeddings`** +`supercache-node -demo-keyspace` (the default) registers **`vectorset`** (`ModeVectorSet`, cosine, dim unlocked until first `vadd`). ```bash @@ -39,21 +39,21 @@ go run ./cmd/supercache-node \ -cache 127.0.0.1:9000 -peer 127.0.0.1:9001 -admin 127.0.0.1:8080 # terminal 2 — add, inspect, search -go run ./cmd/sc -keyspace embeddings vadd products east 1,0 -go run ./cmd/sc -keyspace embeddings vadd products north 0,1 -go run ./cmd/sc -keyspace embeddings vadd products ne 0.7,0.7 -go run ./cmd/sc -keyspace embeddings vcard products -go run ./cmd/sc -keyspace embeddings vdim products -go run ./cmd/sc -keyspace embeddings vemb products east -go run ./cmd/sc -keyspace embeddings vsim products 1,0.05 3 +go run ./cmd/sc -keyspace vectorset vadd products east 1,0 +go run ./cmd/sc -keyspace vectorset vadd products north 0,1 +go run ./cmd/sc -keyspace vectorset vadd products ne 0.7,0.7 +go run ./cmd/sc -keyspace vectorset vcard products +go run ./cmd/sc -keyspace vectorset vdim products +go run ./cmd/sc -keyspace vectorset vemb products east +go run ./cmd/sc -keyspace vectorset vsim products 1,0.05 3 # replace, rem, missing -go run ./cmd/sc -keyspace embeddings vadd products east 0,1 -go run ./cmd/sc -keyspace embeddings vsim products 1,0 3 -go run ./cmd/sc -keyspace embeddings vrem products north -go run ./cmd/sc -keyspace embeddings vcard products -go run ./cmd/sc -keyspace embeddings vdim missing # prints missing, exit 1 +go run ./cmd/sc -keyspace vectorset vadd products east 0,1 +go run ./cmd/sc -keyspace vectorset vsim products 1,0 3 +go run ./cmd/sc -keyspace vectorset vrem products north +go run ./cmd/sc -keyspace vectorset vcard products +go run ./cmd/sc -keyspace vectorset vdim missing # prints missing, exit 1 # cosine rejects a zero vector (L2/IP would allow it on another keyspace) -# go run ./cmd/sc -keyspace embeddings vadd products origin 0,0 +# go run ./cmd/sc -keyspace vectorset vadd products origin 0,0 ```