Files
ofekshenawa a6be8505d0 feat(csc): add standalone client-side caching (#3941)
* feat(csc): add standalone client-side caching (#3748)

* Add local cache

* add context support to Cache.Get, time-gated stale placeholder recovery in Reserve

* fix:Nil waitCh guard causes busy loop ignoring context & cloneBytes conflates nil and empty byte slices

* Refactor local cache and move to internal/cache, defer public surface

* fix GET acquires exclusive lock on every cache hit

* Record cache-hit recency atomically instead of write-locking

* Bound Get's in-progress wait by StaleTimeout

* feat(csc): add command key extraction and caching logic (#3773)

* feat(csc): add command key extraction and caching logic

* fix: lastKey incorrectly reads first key position instead of last

* fix: extractRedisKeys over-extracts non-key arguments as keys

* csc: Support standalone client (#3794)

* feat(csc): add command key extraction and caching logic

* fix: lastKey incorrectly reads first key position instead of last

* fix: extractRedisKeys over-extracts non-key arguments as keys

* CSC: Support standalone client

* fix race condition in tests

* perf(csc): record cache-hit recency atomically instead of write-locking

* fix(csc): bound Get wait by StaleTimeout, restrict CSC to DB 0, warn on RESP2

* Exclude XREAD from cacheable commands

* feat(csc): client-side caching SharedTracking standalone connection (#3851)

* feat(csc): multi-strategy client-side caching

* fix linting issues

* fix spellcheck issues

* Add drainer optimizations

* Fix spellcheck

* Fix bugs and address comments

* Fix csc per connection issues

* Fix Orphan cache after sidecar start error

* Fix clone misses conn eviction hook

* reduce to sharedTracking only

* Address comments

* Address testing issue & remove xpending from cacheable

* Address codex comments

* Remove csc command stat api residue

* fix(csc): harden cache and connection lifecycle

Serialize cache publication with connection removal and reinitialization, evict entries whenever tracking coverage is lost, and preserve CSC lifecycle state across derived clients.

Guard connection-state commands, cache negative replies safely, support wrapped transports with bounded probes, and make background drainers obey pool limits and timeouts.

Add lifecycle, race, transport, negative-cache, command-guard, and derived-client regression coverage and document CSC credential restrictions.

* Address comments

* fix(csc): harden command guards and close handling

- normalize pointer-encoded string arguments consistently with the RESP writer
- detect pointer-based CLIENT TRACKING and SORT_RO BY/GET arguments
- reject raw SUBSCRIBE commands on CSC-managed pooled connections
- preserve typed Pub/Sub support through dedicated connections
- keep ordinary client Close synchronous and return teardown errors
- defer handler-context Close to prevent background drainer self-deadlocks
- serialize concurrent and repeated CSC teardown

* add acl to wordlist

* docs: remove CSC strategy guide from PR

* chore: restore gitignore

* update comment in csc_integration.go to be more accurate

* fix RE test

* Add an example and readme

* fix spellcheck ci

* fix doctests

* fix(csc): harden cache and connection lifecycle

Serialize cache publication with connection lifecycle changes and evict entries when tracking coverage is lost.

* fix issues

* Rename from multiDB to NonZeroDB
2026-07-30 19:02:17 +03:00

983 B

Client-side caching example

This example enables the built-in client-side cache on a standalone go-redis client. It demonstrates:

  • a first read fetched from Redis
  • a repeated read served from the local cache
  • automatic eviction after another client changes the key
  • cache hit and miss statistics through CSCStats

go-redis uses Redis CLIENT TRACKING and RESP3 invalidation notifications to keep the local cache synchronized. Invalidations are asynchronous, so the example waits until the cached client observes the updated value.

Requirements

  • Redis with CLIENT TRACKING support
  • RESP3
  • database 0
  • no dynamic credential provider

Fixed Username and Password values are supported.

Run

The Redis address defaults to localhost:6379. Override it with REDIS_ADDR:

go run .
# or
REDIS_ADDR=localhost:6390 go run .

Expected output:

first read: hello
second read: hello
cache stats: 1 hit, 1 miss
after invalidation: hello again