From 0daa6a7208fe3c1275585d5d8043c8aa600f1760 Mon Sep 17 00:00:00 2001 From: kiro-agent Date: Sun, 26 Jul 2026 08:09:03 +0000 Subject: [PATCH 1/2] docs: add server-assisted CSC and CLIENT TRACKINGINFO for Python, Node, Go Signed-off-by: kiro-agent --- .../client-features/client-side-caching.mdx | 123 ++++++++++++++++-- src/data/available-commands.json | 4 +- 2 files changed, 115 insertions(+), 12 deletions(-) diff --git a/src/content/docs/concepts/client-features/client-side-caching.mdx b/src/content/docs/concepts/client-features/client-side-caching.mdx index ba8f5d27..8daaaeb1 100644 --- a/src/content/docs/concepts/client-features/client-side-caching.mdx +++ b/src/content/docs/concepts/client-features/client-side-caching.mdx @@ -8,7 +8,7 @@ import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; Client-side caching in Valkey GLIDE stores responses from cacheable read commands in a local in-memory cache on the client, reducing network round-trips and server load. When a cached command is issued again, the response is served directly from local memory without contacting the server. ## How It Works @@ -565,15 +565,65 @@ Once enabled, the client receives push invalidation messages from the server whe - Server-assisted invalidation is not yet available in the Python client. Progress is tracked in [issue #5963](https://github.com/valkey-io/valkey-glide/issues/5963). + ```python + from glide import ( + GlideClient, + GlideClientConfiguration, + ClientSideCache, + NodeAddress, + ) + + cache = ClientSideCache.create( + max_cache_kb=1024, + entry_ttl_ms=60_000, + server_assisted=True, # Enable server-assisted invalidation + ) + + config = GlideClientConfiguration( + addresses=[NodeAddress("localhost", 6379)], + client_side_cache=cache, + ) + client = await GlideClient.create(config) + ``` - Server-assisted invalidation is not yet available in the Node.js client. Progress is tracked in [issue #5964](https://github.com/valkey-io/valkey-glide/issues/5964). + ```typescript + import { + GlideClient, + ClientSideCache, + } from "@valkey/valkey-glide"; + + const cache = ClientSideCache.create( + 1024, // maxCacheKb + 60000, // entryTtlMs + { + serverAssisted: true, // Enable server-assisted invalidation + } + ); + + const client = await GlideClient.createClient({ + addresses: [{ host: "localhost", port: 6379 }], + clientSideCache: cache, + }); + ``` - Server-assisted invalidation is not yet available in the Go client. Progress is tracked in [issue #5966](https://github.com/valkey-io/valkey-glide/issues/5966). + ```go + import ( + "github.com/valkey-io/valkey-glide/go/v2/config" + glide "github.com/valkey-io/valkey-glide/go/v2" + ) + + cache := config.NewClientSideCache(1024, 60000). + WithServerAssisted(true) // Enable server-assisted invalidation + + clientConfig := config.NewGlideClientConfiguration(). + WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379}). + WithClientSideCache(cache) + client, err := glide.NewGlideClient(clientConfig) + ``` @@ -612,15 +662,68 @@ The `clientTrackingInfo()` command returns the current tracking state of the con - Not yet available. See [issue #5963](https://github.com/valkey-io/valkey-glide/issues/5963). + ```python + from glide import GlideClient, GlideClusterClient, ClientTrackingInfo + from glide.routes import AllNodes + + # Standalone client + info = await client.client_tracking_info() + # info is a ClientTrackingInfo with: + # info.flags -> set e.g. {"on", "noloop"} + # info.redirect -> int (-1 if not redirecting) + # info.prefixes -> set of monitored key prefixes + + # Cluster client — routes to a random node by default + info = await cluster_client.client_tracking_info() + + # Cluster client — query all nodes + all_info = await cluster_client.client_tracking_info(route=AllNodes()) + # Returns dict[bytes, ClientTrackingInfo] + ``` - Not yet available. See [issue #5964](https://github.com/valkey-io/valkey-glide/issues/5964). + ```typescript + import { ClientTrackingInfo } from "@valkey/valkey-glide"; + + // Standalone client + const info = await client.clientTrackingInfo(); + console.log(info.flags); // Set { "off" } or Set { "on", "noloop" } + console.log(info.redirect); // -1 + console.log(info.prefixes); // Set {} + + // Cluster client — routes to a random node by default + const clusterInfo = await clusterClient.clientTrackingInfo(); + + // Cluster client — query all nodes + const allInfo = await clusterClient.clientTrackingInfo({ route: "allNodes" }); + // allInfo is Record + ``` - Not yet available. See [issue #5966](https://github.com/valkey-io/valkey-glide/issues/5966). + ```go + import ( + "context" + "github.com/valkey-io/valkey-glide/go/v2/models" + "github.com/valkey-io/valkey-glide/go/v2/options" + ) + + ctx := context.Background() + + // Standalone client + info, err := client.ClientTrackingInfo(ctx) + // info.Flags -> []string e.g. ["on", "noloop"] + // info.Redirect -> int64 (-1 if not redirecting) + // info.Prefixes -> []string of monitored key prefixes + + // Cluster client — routes to a random node by default + info, err := clusterClient.ClientTrackingInfo(ctx) + + // Cluster client — query all nodes + result, err := clusterClient.ClientTrackingInfoWithOptions(ctx, options.RouteOption{Route: config.AllNodes}) + // result is ClusterValue[ClientTrackingInfo] + ``` @@ -636,15 +739,15 @@ The `clientTrackingInfo()` command returns the current tracking state of the con | Limitation | Details | | --- | --- | -| **TTL-only expiration** | No server-side invalidation by default. Cached values may become stale if the key is modified on the server before the TTL expires. Java supports [server-assisted invalidation](#server-assisted-invalidation) which eliminates this limitation. | +| **TTL-only expiration** | No server-side invalidation by default. Cached values may become stale if the key is modified on the server before the TTL expires. Java, Python, Node.js, and Go support [server-assisted invalidation](#server-assisted-invalidation) which eliminates this limitation. | | **Lazy expiration** | Expired entries are cleaned up on access, not proactively in the background. | | **Limited command coverage** | Only `GET`, `HGETALL`, and `SMEMBERS` are cached. Other read commands are not cached. | | **NIL not cached** | If a key does not exist, the nil response is not stored. | -| **No invalidation on writes** | In TTL-only mode, writing to a key (e.g., `SET`, `HSET`, `SADD`, `DEL`) does not invalidate the local cache entry — even when the write is issued by the same client that has the value cached. Subsequent reads return the stale value until its TTL expires or it is evicted under memory pressure. With [server-assisted mode](#server-assisted-invalidation) (Java), the server pushes invalidation messages that clear the stale entry immediately. | +| **No invalidation on writes** | In TTL-only mode, writing to a key (e.g., `SET`, `HSET`, `SADD`, `DEL`) does not invalidate the local cache entry — even when the write is issued by the same client that has the value cached. Subsequent reads return the stale value until its TTL expires or it is evicted under memory pressure. With [server-assisted mode](#server-assisted-invalidation) (Java, Python, Node.js, Go), the server pushes invalidation messages that clear the stale entry immediately. | ### Compatibility with managed services -The Java client now supports server-assisted invalidation via `CLIENT TRACKING`. When using this feature, the deployment must expose the `CLIENT TRACKING` command. The table below summarizes compatibility: +Java, Python, Node.js, and Go clients now support server-assisted invalidation via `CLIENT TRACKING`. When using this feature, the deployment must expose the `CLIENT TRACKING` command. The table below summarizes compatibility: | Deployment | Exposes `CLIENT TRACKING`? | Notes | | ------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/src/data/available-commands.json b/src/data/available-commands.json index dee5bc81..c3ed0cad 100644 --- a/src/data/available-commands.json +++ b/src/data/available-commands.json @@ -89,8 +89,8 @@ { "command": "CLIENT REPLY", "valkey-io": "/commands/client-reply", "python": "not_available", "node": "not_available", "java": "not_available", "go": "not_available", "csharp": "not_available", "php": "not_available", "href": "#incompatible-commands" }, { "command": "CLIENT SETINFO", "valkey-io": "/commands/client-setinfo", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "available", "php": "available" }, { "command": "CLIENT SETNAME", "valkey-io": "/commands/client-setname", "python": "not_available", "node": "not_available", "java": "not_available", "go": "available", "csharp": "not_available", "php": "not_available", "python-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "node-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "java-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, - { "command": "CLIENT TRACKING", "valkey-io": "/commands/client-tracking", "python": "not_available", "node": "not_available", "java": "available", "go": "not_available", "csharp": "not_available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#server-assisted-invalidation", "python-href": "https://github.com/valkey-io/valkey-glide/issues/5963", "node-href": "https://github.com/valkey-io/valkey-glide/issues/5964", "go-href": "https://github.com/valkey-io/valkey-glide/issues/5966", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6010", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, - { "command": "CLIENT TRACKINGINFO", "valkey-io": "/commands/client-trackinginfo", "python": "not_available", "node": "not_available", "java": "available", "go": "not_available", "csharp": "not_available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#diagnosing-tracking-state-with-clienttrackinginfo", "python-href": "https://github.com/valkey-io/valkey-glide/issues/5963", "node-href": "https://github.com/valkey-io/valkey-glide/issues/5964", "go-href": "https://github.com/valkey-io/valkey-glide/issues/5966", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6010", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, + { "command": "CLIENT TRACKING", "valkey-io": "/commands/client-tracking", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "not_available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#server-assisted-invalidation", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6010", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, + { "command": "CLIENT TRACKINGINFO", "valkey-io": "/commands/client-trackinginfo", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "not_available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#diagnosing-tracking-state-with-clienttrackinginfo", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6010", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, { "command": "CLIENT UNBLOCK", "valkey-io": "/commands/client-unblock", "python": "not_available", "node": "not_available", "java": "not_available", "go": "not_available", "csharp": "not_available", "php": "not_available", "href": "#incompatible-commands" }, { "command": "CLIENT UNPAUSE", "valkey-io": "/commands/client-unpause", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "not_available", "php": "not_available", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, { "command": "ECHO", "valkey-io": "/commands/echo", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "available", "php": "available" }, From 7a29729004841f7510c377e97d8e50aa7acc0bee Mon Sep 17 00:00:00 2001 From: kiro-agent Date: Sun, 26 Jul 2026 08:55:38 +0000 Subject: [PATCH 2/2] docs: add C# server-assisted CSC and CLIENT TRACKINGINFO Signed-off-by: kiro-agent --- .../client-features/client-side-caching.mdx | 38 ++++++++++++++++--- src/data/available-commands.json | 4 +- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/content/docs/concepts/client-features/client-side-caching.mdx b/src/content/docs/concepts/client-features/client-side-caching.mdx index 8daaaeb1..813561fa 100644 --- a/src/content/docs/concepts/client-features/client-side-caching.mdx +++ b/src/content/docs/concepts/client-features/client-side-caching.mdx @@ -8,7 +8,7 @@ import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; Client-side caching in Valkey GLIDE stores responses from cacheable read commands in a local in-memory cache on the client, reducing network round-trips and server load. When a cached command is issued again, the response is served directly from local memory without contacting the server. ## How It Works @@ -631,7 +631,19 @@ Once enabled, the client receives push invalidation messages from the server whe - Server-assisted invalidation is not yet available in the C# client. Progress is tracked in [issue #6010](https://github.com/valkey-io/valkey-glide/issues/6010). + ```csharp + using Valkey.Glide; + using static Valkey.Glide.ConnectionConfiguration; + + var cache = new ClientSideCacheConfig(maxCacheKb: 1024, entryTtl: TimeSpan.FromSeconds(60)) + .WithServerAssisted(true); // Enable server-assisted invalidation + + var config = new StandaloneClientConfigurationBuilder() + .WithAddress("localhost", 6379) + .WithClientSideCache(cache) + .Build(); + var client = await GlideClient.CreateClient(config); + ``` @@ -731,7 +743,21 @@ The `clientTrackingInfo()` command returns the current tracking state of the con - Not yet available. See [issue #6010](https://github.com/valkey-io/valkey-glide/issues/6010). + ```csharp + using Valkey.Glide; + + // Standalone client + ClientTrackingInfo info = await client.ClientTrackingInfoAsync(); + // info.Flags -> IReadOnlySet e.g. {"on", "noloop"} + // info.Redirect -> long (-1 if not redirecting) + // info.Prefixes -> IReadOnlySet of monitored key prefixes + + // Cluster client — routes to a random node by default + ClientTrackingInfo clusterInfo = (await clusterClient.ClientTrackingInfoAsync(Route.Random)).SingleValue; + + // Cluster client — query all nodes + ClusterValue allInfo = await clusterClient.ClientTrackingInfoAsync(Route.AllNodes); + ``` @@ -739,15 +765,15 @@ The `clientTrackingInfo()` command returns the current tracking state of the con | Limitation | Details | | --- | --- | -| **TTL-only expiration** | No server-side invalidation by default. Cached values may become stale if the key is modified on the server before the TTL expires. Java, Python, Node.js, and Go support [server-assisted invalidation](#server-assisted-invalidation) which eliminates this limitation. | +| **TTL-only expiration** | No server-side invalidation by default. Cached values may become stale if the key is modified on the server before the TTL expires. Java, Python, Node.js, Go, and C# support [server-assisted invalidation](#server-assisted-invalidation) which eliminates this limitation. | | **Lazy expiration** | Expired entries are cleaned up on access, not proactively in the background. | | **Limited command coverage** | Only `GET`, `HGETALL`, and `SMEMBERS` are cached. Other read commands are not cached. | | **NIL not cached** | If a key does not exist, the nil response is not stored. | -| **No invalidation on writes** | In TTL-only mode, writing to a key (e.g., `SET`, `HSET`, `SADD`, `DEL`) does not invalidate the local cache entry — even when the write is issued by the same client that has the value cached. Subsequent reads return the stale value until its TTL expires or it is evicted under memory pressure. With [server-assisted mode](#server-assisted-invalidation) (Java, Python, Node.js, Go), the server pushes invalidation messages that clear the stale entry immediately. | +| **No invalidation on writes** | In TTL-only mode, writing to a key (e.g., `SET`, `HSET`, `SADD`, `DEL`) does not invalidate the local cache entry — even when the write is issued by the same client that has the value cached. Subsequent reads return the stale value until its TTL expires or it is evicted under memory pressure. With [server-assisted mode](#server-assisted-invalidation) (Java, Python, Node.js, Go, C#), the server pushes invalidation messages that clear the stale entry immediately. | ### Compatibility with managed services -Java, Python, Node.js, and Go clients now support server-assisted invalidation via `CLIENT TRACKING`. When using this feature, the deployment must expose the `CLIENT TRACKING` command. The table below summarizes compatibility: +Java, Python, Node.js, Go, and C# clients now support server-assisted invalidation via `CLIENT TRACKING`. When using this feature, the deployment must expose the `CLIENT TRACKING` command. The table below summarizes compatibility: | Deployment | Exposes `CLIENT TRACKING`? | Notes | | ------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/src/data/available-commands.json b/src/data/available-commands.json index c3ed0cad..46a3d3cc 100644 --- a/src/data/available-commands.json +++ b/src/data/available-commands.json @@ -89,8 +89,8 @@ { "command": "CLIENT REPLY", "valkey-io": "/commands/client-reply", "python": "not_available", "node": "not_available", "java": "not_available", "go": "not_available", "csharp": "not_available", "php": "not_available", "href": "#incompatible-commands" }, { "command": "CLIENT SETINFO", "valkey-io": "/commands/client-setinfo", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "available", "php": "available" }, { "command": "CLIENT SETNAME", "valkey-io": "/commands/client-setname", "python": "not_available", "node": "not_available", "java": "not_available", "go": "available", "csharp": "not_available", "php": "not_available", "python-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "node-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "java-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, - { "command": "CLIENT TRACKING", "valkey-io": "/commands/client-tracking", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "not_available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#server-assisted-invalidation", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6010", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, - { "command": "CLIENT TRACKINGINFO", "valkey-io": "/commands/client-trackinginfo", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "not_available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#diagnosing-tracking-state-with-clienttrackinginfo", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6010", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, + { "command": "CLIENT TRACKING", "valkey-io": "/commands/client-tracking", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#server-assisted-invalidation", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, + { "command": "CLIENT TRACKINGINFO", "valkey-io": "/commands/client-trackinginfo", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "available", "php": "not_available", "href": "/concepts/client-features/client-side-caching/#diagnosing-tracking-state-with-clienttrackinginfo", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, { "command": "CLIENT UNBLOCK", "valkey-io": "/commands/client-unblock", "python": "not_available", "node": "not_available", "java": "not_available", "go": "not_available", "csharp": "not_available", "php": "not_available", "href": "#incompatible-commands" }, { "command": "CLIENT UNPAUSE", "valkey-io": "/commands/client-unpause", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "not_available", "php": "not_available", "csharp-href": "https://github.com/valkey-io/valkey-glide/issues/6292", "php-href": "https://github.com/valkey-io/valkey-glide/issues/6292" }, { "command": "ECHO", "valkey-io": "/commands/echo", "python": "available", "node": "available", "java": "available", "go": "available", "csharp": "available", "php": "available" },