Skip to content

Hitless demo: smart client handoffs TUI (BYO Redis Enterprise cluster) - #5

Merged
mgravell merged 5 commits into
mainfrom
hitless-demo
Nov 4, 2026
Merged

mgravell merged 5 commits into
mainfrom
hitless-demo

Conversation

@mgravell

@mgravell mgravell commented Nov 4, 2026

Copy link
Copy Markdown
Member

Adds hitless/, an interactive TUI for SE.Redis maintenance notifications (smart client handoffs / hitless upgrades), alongside the caching and geo failover demos.

Bring your own server. The notifications are a Redis Enterprise proxy feature, so unlike the other demos this one has no Docker setup: it needs a Redis Enterprise cluster (or Redis Cloud database) with the maintenance-notification flags on. The README says exactly what the cluster needs and the database shape used. With Redis's fault injector available, the fault keys drive it directly against the existing database by bdb_id; without it, each key shows the rladmin command to run by hand and everything else works the same.

What it shows

  • continuous SET/GET traffic from eight workers: completed and failed ops per 250ms, worst latency on a log scale
  • every notification (MOVING, MIGRATING/MIGRATED, FAILING_OVER/FAILED_OVER, slot migration), every handoff and connection failure, and the library's own log lines about the feature
  • which proxy node the connection is actually on (CLIENT INFO), so a MOVING visibly changes it
  • a one-line summary per disruption: each notification with its offset, handoff, restore, server close, failed ops, worst latency
  • toggles that reconnect: maintNotifications (Auto/Enabled/Disabled), maintMovingEndpointType, RESP3/RESP2, database; WithRetry() without reconnecting
  • faults: endpoint rebind, migrate, failover, maintenance mode, and an unannounced proxy restart as the control

Configuration comes from the fault injector's endpoints.json, a gitignored hitless.local.json, CLI flags or HITLESS_* environment variables (a leading ~/ is expanded, so a shell profile can hold it). Hands-free runs (--fire M --fire-after 8 --quit-after 80 --transcript) capture a whole episode as a transcript. -p:SERProject=<csproj> builds against a local library instead of the NuGet package.

Measured live on a 3-node RS 8.0.22 cluster; the README has a table of what to expect from each fault with notifications off and on. The first live run exposed a drain bug in 3.4.31 (the MOVING handoff recycled at the end of the window under steady load, failing in-flight commands); that is seredis/StackExchange.Redis#3335, and the README's "0 failed" column is with that fix.

Pins StackExchange.Redis 3.4.31; the root README gains a row.

…, optional fault injector)

Continuous SET/GET traffic on one connection; every maintenance notification,
handoff and failure on screen with a per-disruption summary. Toggles for
maintNotifications, maintMovingEndpointType, RESP3/RESP2, database and
WithRetry(). Faults (endpoint rebind, migrate, failover, maintenance mode,
unannounced proxy restart) through the fault injector by bdb id, or shown as
rladmin commands to run by hand. Pins StackExchange.Redis 3.4.31.
…verride

HITLESS_ENDPOINTS and friends expand a leading ~/ and HITLESS_MODE picks the
starting mode, so a shell profile can hold the whole configuration. --fire
<key> --fire-after --quit-after press one fault key and exit on a timer, for
a smoke test or a scripted run with --transcript. -p:SERProject=<csproj>
builds against a local library instead of the NuGet package, which is how the
MOVING drain fix (StackExchange.Redis PR #3335) was verified live. The MOVING
event line no longer labels the successor as shards; the connected: line
formats the endpoint.
…project does not exist

The shell does not expand ~ after = inside -p:, so MSBuild got a literal ~/...; a
ProjectReference to a missing path is silently empty, and with the package
reference conditioned off the compile had no library at all.
… notifications

Measured on the live cluster: the rebind is the before-and-after, migration
and failover never drop the connection in either mode, maintenance mode only
reaches the proxy if it was on the drained node, and the proxy restart is
identical in both modes by design. Notes the bounded size of an unannounced
close and the 3.4.31 drain bug fixed in SE.Redis PR #3335.
@mgravell
mgravell merged commit 1e1adfa into main Nov 4, 2026
@mgravell
mgravell deleted the hitless-demo branch November 4, 2026 17:04
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