Skip to content

feat: ModeStream (Redis-like append-only log) - #50

Merged
Code0987 merged 1 commit into
mainfrom
feat/mode-stream
Sep 8, 2026
Merged

Code0987 merged 1 commit into
mainfrom
feat/mode-stream

Conversation

@Code0987

@Code0987 Code0987 commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

New keyspace mode ModeStream: a Redis-like append-only log with owner-minted millis-seq ids and one opaque []byte payload.

Design: docs/design/2026-09-08-mode-stream.md

What landed vs the design

  • Engine / client / Cache RPCs: XAdd, XRange, XRevRange, XLen, XDel, XTrim; existing Delete(name) tombstones the stream
  • Exclusive start is a leading ( on start; end is always inclusive
  • Owner mints ids; non-owner XAdd uses peer StreamAdd and returns the id
  • Snapshot fan-out (FlagStream + Value[0] S); inbox A/D/T stays owner-only
  • Entry.Flags widened to uint64; FlagStream = 1<<32
  • XRevRange uses the same start/end window as XRange (newest first) — not Redis high-then-low argument order
  • Hard cap 4096 → stream full; client rejects int32 overflow on XTrim / range count
  • sc xadd|xlen|xrange|xrevrange|xdel|xtrim
  • Not in this PR (design non-goals): consumer groups, blocking XREAD, caller-chosen ids, Lab widget, examples/stream

Product docs

Updated in this PR: docs/API.md, api/openapi/cache.openapi.yaml + docs/api snapshot (0.14.0), PLAN.md, docs/OPERATIONS.md, docs/CLUSTER_FLOWS.md, README.md, cmd/sc help/README, docs/design/README.md.

Test plan

  • go test ./... (local, green)
  • Local micros: StoreGetHit 2 allocs/op, EngineGetHit 15 allocs/op (flat)
  • CI test + bench; read <!-- supercache-bench-comment -->

Bench risk

  • Hot path? Get-hit / StoreGetHit: no if Stream is not on those benches.
  • Flags uint32uint64 widens store.Entry by 4 bytes. Could move StoreGetHit ns/op; must not raise Get-hit / StoreGetHit allocs/op.
  • No new scbench cells.
  • Gate: shared smoke ±10%; Get-hit allocs flat.

Add ModeStream: XAdd/XRange/XRevRange/XLen/XDel/XTrim with owner-minted
millis-seq ids and a single opaque []byte payload. Snapshot fan-out
(FlagStream + S/A/D/T); non-owner XAdd uses peer StreamAdd.

Entry.Flags is uint64 so FlagStream can be 1<<32. XRevRange uses the
same start/end window as XRange (newest first). Hard cap 4096 returns
stream full. Client rejects int32 overflow on XTrim/count.
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

SuperCache bench vs main

Both sides ran once on this same GitHub runner (main, then this PR). Not a merge gate.

Baseline: dab9d3c (2026-09-08T08:30:11Z) → this run: dab9d3c (2026-09-08T08:29:24Z)

scbench smoke

cell ops/s (main → PR) Δ ops/s p50 p99
get/hit n=1 c=1 uniform 8574 → 8742 +2.0% 116µs → 114µs 195µs → 189µs
get/hit n=1 c=10 uniform 33495 → 33634 +0.4% 271µs → 268µs 823µs → 821µs
get/hit n=3 c=10 uniform 38766 → 39093 +0.8% 227µs → 225µs 892µs → 897µs
miss/miss-cacheonly n=1 c=1 uniform 8540 → 8424 -1.4% 116µs → 117µs 213µs → 218µs
miss/miss-cacheonly n=1 c=10 uniform 35521 → 33617 -5.4% 254µs → 268µs 804µs → 881µs
set/put n=1 c=1 uniform 8361 → 8484 +1.5% 117µs → 116µs 223µs → 208µs
set/put n=1 c=10 uniform 32543 → 33229 +2.1% 279µs → 274µs 851µs → 815µs

Δ ops/s: green-ish is higher throughput. Latency: lower is better.

go test -bench (ns/op)

benchmark ns/op (main → PR) Δ allocs/op
BenchmarkEngineDelete 783 → 847 +8.1% 6 → 6
BenchmarkEngineGetHit 1234 → 1252 +1.5% 15 → 15
BenchmarkEngineGetHitParallel 1312 → 1199 -8.6% 15 → 15
BenchmarkEngineGetMissCacheOnly 860 → 897 +4.3% 14 → 14
BenchmarkEngineGetMissCacheOnlyParallel 635 → 635 +0.0% 14 → 14
BenchmarkEngineGetMissLoadThrough 1609 → 1620 +0.7% 24 → 24
BenchmarkEngineGetMissLoadThroughParallel 1873 → 1823 -2.7% 23 → 23
BenchmarkEnginePut 1582 → 1623 +2.6% 18 → 18
BenchmarkEnginePutParallel 1386 → 1458 +5.2% 18 → 18
BenchmarkStoreBitSet 113 → 113 +0.2% 1 → 1
BenchmarkStoreCGetHit 73 → 77 +5.5% 0 → 0
BenchmarkStoreCIncr 101 → 105 +3.3% 1 → 1
BenchmarkStoreCMSIncr 121 → 123 +1.3% 0 → 0
BenchmarkStoreCMSIncrN 121 → 121 -0.1% 0 → 0
BenchmarkStoreGeoAdd 9532 → 10127 +6.2% 2 → 2
BenchmarkStoreGeoPosHit 89 → 89 +0.2% 0 → 0
BenchmarkStoreGeoPosMiss 87 → 87 +0.3% 0 → 0
BenchmarkStoreGetHit 292 → 293 +0.5% 2 → 2
BenchmarkStoreGetHitParallel 357 → 346 -3.0% 2 → 2
BenchmarkStoreHGetHit 91 → 92 +0.9% 1 → 1
BenchmarkStoreHGetMiss 85 → 84 -0.5% 0 → 0
BenchmarkStoreHLLAdd 100 → 103 +3.2% 0 → 0
BenchmarkStoreHSet 10570 → 10980 +3.9% 3 → 3
BenchmarkStoreJsonSet 26797 → 26757 -0.1% 207 → 207
BenchmarkStorePut 304 → 343 +12.7% 2 → 2
BenchmarkStorePutParallel 352 → 362 +2.9% 2 → 2
BenchmarkStoreSetAdd 9213 → 9169 -0.5% 2 → 2
BenchmarkStoreSetContainsHit 87 → 88 +0.3% 0 → 0
BenchmarkStoreSetContainsMiss 84 → 84 -0.5% 0 → 0
BenchmarkStoreTopKAdd 996 → 992 -0.4% 20 → 20
BenchmarkStoreVAdd 107749 → 108433 +0.6% 512 → 512
BenchmarkStoreVSim 89438 → 90059 +0.7% 530 → 530
BenchmarkStoreZAdd 9862 → 9552 -3.1% 2 → 2
BenchmarkStoreZScoreHit 86 → 86 -0.4% 0 → 0
BenchmarkStoreZScoreMiss 86 → 86 +0.2% 0 → 0

Posted by CI bench job. Not a merge gate.

@Code0987
Code0987 merged commit c5a6051 into main Sep 8, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant