From 4465b6ad64b5356d14dd5bdd3e823e9b24a25b96 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 18 Sep 2026 09:53:50 +0100 Subject: [PATCH 1/3] DOC-7027: Document StackExchange.Redis smart client handoffs (3.3.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3.3.0 shipped the maintenance-notifications feature as PR #3191, which superseded the original 4-PR series this ticket was pinned to (that series' commits diverged; #3191 reimplemented it). Verified the shipped API directly against the 3.3.0 source rather than the PR description, which paid off twice: - The PR body claims the Redis Cloud/Enterprise/AMR provider profiles "turn it on where it is supported." The actual provider source has those MaintenanceNotifications overrides commented out — every profile inherits Disabled. Documented the real behavior; readers must set `maintNotifications` explicitly regardless of provider. - `PushMaintenanceEvent` (the new, [Experimental]/SER010 type) turns out to derive from the existing `ServerMaintenanceEvent` base class and is raised through the *same* `ConnectionMultiplexer.ServerMaintenanceEvent` event already documented on produsage.md for Azure's maintenance notifications. Same event, two possible event-args types. Added a disambiguation note on produsage.md and a type-check example on the new connect.md section so readers don't conflate the two. Added the SCH section to dotnet/connect.md (config keys, parameter table, event handling), a StackExchange.Redis row to the cross-client sch.md matrix (with a note that this client's support is still [Experimental], unlike the other rows), and cross-links both ways. Co-Authored-By: Claude Sonnet 5 --- content/develop/clients/dotnet/connect.md | 86 +++++++++++++++++++++ content/develop/clients/dotnet/produsage.md | 5 ++ content/develop/clients/sch.md | 8 ++ 3 files changed, 99 insertions(+) diff --git a/content/develop/clients/dotnet/connect.md b/content/develop/clients/dotnet/connect.md index 9252c0aab4..39b8073bb5 100644 --- a/content/develop/clients/dotnet/connect.md +++ b/content/develop/clients/dotnet/connect.md @@ -130,6 +130,92 @@ conn.StringSet("foo", "bar"); Console.WriteLine(conn.StringGet("foo")); ``` +## Connect using Smart client handoffs (SCH) + +*Smart client handoffs (SCH)* is a feature of Redis Cloud and +Redis Software servers that lets them actively notify clients +about planned server maintenance shortly before it happens. This +lets a client take action to avoid disruptions in service. +See [Smart client handoffs](/content/develop/clients/sch.md) +for more information about SCH. + +> [!NOTE] +> SCH support in `StackExchange.Redis` requires v3.3.0 or later. The feature +> is functional and tested against real Redis Enterprise deployments, but +> because it is a large, new API surface, the types and members involved are +> marked with the `[Experimental]` attribute so that the library can reserve +> the right to adjust them without the usual backwards-compatibility +> guarantees. As a result, the compiler reports the `SER010` diagnostic when +> you use them. Suppressing this diagnostic is the normal way to use the +> feature. To do so, either add the following to your `.csproj` file: +> +> ```xml +> $(NoWarn);SER010 +> ``` +> +> or suppress it locally in your source file: +> +> ```csharp +> #pragma warning disable SER010 +> ``` + +SCH is disabled by default. Enable it with the `MaintenanceNotifications` +configuration option, either in code or using the `maintNotifications` key +in a configuration string: + +```csharp +var options = ConfigurationOptions.Parse("host:6379,maintNotifications=Auto,maintRelaxedTimeout=15"); + +// or, in code: +var options = new ConfigurationOptions { + EndPoints = { "host:6379" }, + MaintenanceNotifications = MaintenanceNotificationMode.Auto, + MaintenanceRelaxedTimeout = TimeSpan.FromSeconds(15), +}; + +var muxer = await ConnectionMultiplexer.ConnectAsync(options); +``` + +> [!NOTE] +> `ConfigurationOptions` also has a `Defaults` property that accepts named +> provider profiles (`amr`, `rediscloud`, `enterprise`) using the `defaults` +> configuration key. As of v3.3.0, none of these profiles override +> `MaintenanceNotifications`, so it stays `Disabled` under every profile. +> Set `maintNotifications` explicitly, regardless of which server product +> you connect to. + +The `ConfigurationOptions` object accepts the following SCH-related parameters: + +| Name | Description | +| :-- | :-- | +| `MaintenanceNotifications` | Whether to request SCH. The options are `Disabled` (the default), `Enabled` (require SCH and reject the connection, including a fallback to RESP2, if the server can't deliver it), and `Auto` (request SCH and tolerate a server that doesn't support it). | +| `MaintenanceMovingEndpointType` | Which endpoint type to request for a replacement node during a handoff. The options are `ServerDefault` (no preference), `Auto` (the default; derived from the connection's scheme and encryption), `InternalIp`, `InternalFqdn`, `ExternalIp`, `ExternalFqdn`, and `None`. | +| `MaintenanceRelaxedTimeout` | The timeout to use for commands and connections while the server has announced maintenance. The default is 10 seconds. | +| `MaintenanceRelaxedWindowMax` | The maximum time to keep using the relaxed timeout if no notification arrives to close the window. The default is three times `MaintenanceRelaxedTimeout`. | +| `MaintenancePostEventRelaxedDuration` | How long to keep using the relaxed timeout after a closing notification, to cover trailing effects of the maintenance. | + +Subscribe to the `ConnectionMultiplexer.ServerMaintenanceEvent` event to +observe SCH notifications. This is the same event that some servers (such as +Azure Cache for Redis) already use for their own maintenance notifications +(see [Production usage](/content/develop/clients/dotnet/produsage.md#server-notification-events)), +so check the runtime type of the event args to tell the two apart: + +```csharp +muxer.ServerMaintenanceEvent += (object sender, ServerMaintenanceEvent e) => { + if (e is PushMaintenanceEvent pme) { + // A server-native SCH notification. + Console.WriteLine($"SCH notification: {pme.NotificationType} at {pme.EndPoint}"); + } else { + // An older, provider-specific notification (for example, from Azure Cache for Redis). + Console.WriteLine($"Maintenance event: {e.RawMessage}"); + } +}; +``` + +`RedisConnectionException` and `RedisTimeoutException` both expose a +`MaintenanceType` property, so you can tell whether a failure happened +because of ongoing maintenance. + ## Multiplexing Although example code typically works with a single connection, diff --git a/content/develop/clients/dotnet/produsage.md b/content/develop/clients/dotnet/produsage.md index 86d5550695..be0e90f7a7 100644 --- a/content/develop/clients/dotnet/produsage.md +++ b/content/develop/clients/dotnet/produsage.md @@ -58,6 +58,11 @@ docs for the full list of supported events). For example, you could inform users who try to connect that service is temporarily unavailable rather than letting them run into errors. +The same event also carries +[Smart client handoffs](/content/develop/clients/dotnet/connect.md#connect-using-smart-client-handoffs-sch) +(SCH) notifications, which are a different, Redis Cloud- and Redis Software-specific +mechanism. Check the runtime type of the event args to tell the two apart. + ```cs using StackExchange.Redis; diff --git a/content/develop/clients/sch.md b/content/develop/clients/sch.md index 48761f870d..d69c2677f3 100644 --- a/content/develop/clients/sch.md +++ b/content/develop/clients/sch.md @@ -18,6 +18,7 @@ relatedPages: - /develop/clients/nodejs/connect#connect-using-smart-client-handoffs-sch - /develop/clients/lettuce/connect#connect-using-smart-client-handoffs-sch - /develop/clients/go/connect#connect-using-smart-client-handoffs-sch +- /develop/clients/dotnet/connect#connect-using-smart-client-handoffs-sch topics: - smart-client-handoffs - resilience @@ -72,6 +73,13 @@ and the versions that added support for basic connections and | [node-redis](/content/develop/clients/nodejs/connect.md#connect-using-smart-client-handoffs-sch) | v5.9.0 | v5.11.0 | Disabled | | [Lettuce](/content/develop/clients/lettuce/connect.md#connect-using-smart-client-handoffs-sch) | v7.0.0 | - | Disabled | | [go-redis](/content/develop/clients/go/connect.md#connect-using-smart-client-handoffs-sch) | v9.16.0 | v9.18.0 | Disabled | +| [StackExchange.Redis](/content/develop/clients/dotnet/connect.md#connect-using-smart-client-handoffs-sch) | v3.3.0 | v3.3.0 | Disabled | + +> [!NOTE] +> SCH support in StackExchange.Redis is marked `[Experimental]`, so the API may +> still change. See +> [Connect using Smart client handoffs (SCH)](/content/develop/clients/dotnet/connect.md#connect-using-smart-client-handoffs-sch) +> for details. > [!NOTE] > SCH is currently disabled when a client is configured for From 5d8fa69b14faac27b9361536b65865e12408c1a5 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 18 Sep 2026 10:36:15 +0100 Subject: [PATCH 2/3] DOC-7027 manual style fixes --- content/develop/clients/dotnet/connect.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/develop/clients/dotnet/connect.md b/content/develop/clients/dotnet/connect.md index 39b8073bb5..4edd4c78ab 100644 --- a/content/develop/clients/dotnet/connect.md +++ b/content/develop/clients/dotnet/connect.md @@ -142,18 +142,18 @@ for more information about SCH. > [!NOTE] > SCH support in `StackExchange.Redis` requires v3.3.0 or later. The feature > is functional and tested against real Redis Enterprise deployments, but -> because it is a large, new API surface, the types and members involved are -> marked with the `[Experimental]` attribute so that the library can reserve -> the right to adjust them without the usual backwards-compatibility +> because it is a large, new API, the types and members involved are +> marked with the `[Experimental]` attribute. This is so the developers can reserve +> the right to adjust the API without the usual backwards-compatibility > guarantees. As a result, the compiler reports the `SER010` diagnostic when -> you use them. Suppressing this diagnostic is the normal way to use the -> feature. To do so, either add the following to your `.csproj` file: +> you use them. You can suppress this diagnostic by adding the following to +> your `.csproj` file: > > ```xml > $(NoWarn);SER010 > ``` > -> or suppress it locally in your source file: +> Alternatively, you can suppress it locally in your source file: > > ```csharp > #pragma warning disable SER010 @@ -189,7 +189,7 @@ The `ConfigurationOptions` object accepts the following SCH-related parameters: | Name | Description | | :-- | :-- | | `MaintenanceNotifications` | Whether to request SCH. The options are `Disabled` (the default), `Enabled` (require SCH and reject the connection, including a fallback to RESP2, if the server can't deliver it), and `Auto` (request SCH and tolerate a server that doesn't support it). | -| `MaintenanceMovingEndpointType` | Which endpoint type to request for a replacement node during a handoff. The options are `ServerDefault` (no preference), `Auto` (the default; derived from the connection's scheme and encryption), `InternalIp`, `InternalFqdn`, `ExternalIp`, `ExternalFqdn`, and `None`. | +| `MaintenanceMovingEndpointType` | The endpoint type to request for a replacement node during a handoff. The options are `ServerDefault` (no preference), `Auto` (the default; derived from the connection's scheme and encryption), `InternalIp`, `InternalFqdn`, `ExternalIp`, `ExternalFqdn`, and `None`. | | `MaintenanceRelaxedTimeout` | The timeout to use for commands and connections while the server has announced maintenance. The default is 10 seconds. | | `MaintenanceRelaxedWindowMax` | The maximum time to keep using the relaxed timeout if no notification arrives to close the window. The default is three times `MaintenanceRelaxedTimeout`. | | `MaintenancePostEventRelaxedDuration` | How long to keep using the relaxed timeout after a closing notification, to cover trailing effects of the maintenance. | @@ -198,7 +198,7 @@ Subscribe to the `ConnectionMultiplexer.ServerMaintenanceEvent` event to observe SCH notifications. This is the same event that some servers (such as Azure Cache for Redis) already use for their own maintenance notifications (see [Production usage](/content/develop/clients/dotnet/produsage.md#server-notification-events)), -so check the runtime type of the event args to tell the two apart: +so check the runtime type of the event arguments to tell the two apart: ```csharp muxer.ServerMaintenanceEvent += (object sender, ServerMaintenanceEvent e) => { From c07397f2da86ba6b5e25ba5d1ac2c1ba8afe99b4 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 18 Sep 2026 10:39:59 +0100 Subject: [PATCH 3/3] DOC-7027 more manual fixes --- content/develop/clients/dotnet/produsage.md | 2 +- content/develop/clients/sch.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/content/develop/clients/dotnet/produsage.md b/content/develop/clients/dotnet/produsage.md index be0e90f7a7..2dbcc427cd 100644 --- a/content/develop/clients/dotnet/produsage.md +++ b/content/develop/clients/dotnet/produsage.md @@ -61,7 +61,7 @@ rather than letting them run into errors. The same event also carries [Smart client handoffs](/content/develop/clients/dotnet/connect.md#connect-using-smart-client-handoffs-sch) (SCH) notifications, which are a different, Redis Cloud- and Redis Software-specific -mechanism. Check the runtime type of the event args to tell the two apart. +mechanism. Check the runtime type of the event arguments to tell the two apart. ```cs using StackExchange.Redis; diff --git a/content/develop/clients/sch.md b/content/develop/clients/sch.md index d69c2677f3..b34110d6ed 100644 --- a/content/develop/clients/sch.md +++ b/content/develop/clients/sch.md @@ -80,6 +80,7 @@ and the versions that added support for basic connections and > still change. See > [Connect using Smart client handoffs (SCH)](/content/develop/clients/dotnet/connect.md#connect-using-smart-client-handoffs-sch) > for details. +  > [!NOTE] > SCH is currently disabled when a client is configured for