Repository navigation
DOC-7176 Document node-redis geographic failover [PARKED] - #4251
Open
andy-stark-redis wants to merge 1 commit into
Open
andy-stark-redis wants to merge 1 commit into
andy-stark-redis wants to merge 1 commit into
Conversation
Add nodejs/failover.md for the experimental multi-db client in redis@6.4.0-beta.0 (createMultiDbClient / ClientPool / Cluster / Sentinel), add node-redis to the overview support table and relatedPages, and link it from nodejs/produsage.md. Structure follows the redis-py and Lettuce failover pages, with node-redis-specific sections where behavior differs: no command retry (a Retries section replaces the retry-config section), failback off by default, initialAvailability MAJORITY meaning both of two endpoints, "Transactions and connection state" (WATCH/multi/scanIterator/legacy, SELECT/MONITOR/emitInvalidate rejected), and a connect() troubleshooting entry. Every JS block on the page was extracted from the markdown and run against redis@6.4.0-beta.0 with two redis:8.8 containers on ports 6401/6402, using docker pause to simulate an unresponsive server. The surprise: a paused server (connection still open, no replies) leaves in-flight commands pending until it answers, even after the client has failed over. commandOptions.timeout does not help, because commands-queue.ts drops a command's timeout once it is written to the socket. Only socket.socketTimeout rejects them. But defaultReconnectStrategy returns false on SocketTimeoutError (socket.ts:525), so socketTimeout alone makes the endpoint emit member-end and never fail back. The page therefore pairs socketTimeout with an always-reconnect reconnectStrategy; the full failover -> recovery -> fallback cycle was verified with that pair, with no idle reconnect churn while health checks run. Running the page's own blocks also caught two draft errors: healthCheck.timeout must be less than interval (default timeout 3000, so lowering interval alone throws at construction), and releasePin() does not switch back, it only re-enables fallback. Learned: socketTimeout is the only way to reject in-flight commands on an unresponsive server, and it needs a custom reconnectStrategy Learned: running the page's extracted code blocks caught 2 defects that reading the source had not Gaps: LagAwareHealthCheck success path unverified (no Redis Software cluster); only constructed and probed against unresolvable hosts Gaps: createMultiDbClientPool/Cluster/Sentinel factories not run; only createMultiDbClient was exercised Gaps: CommandAbandonedError for queued unsent commands taken from upstream docs/multi-db.md, not reproduced Recheck: when redis@6.4.0 stable ships, every identifier and default on the page (all were read from the 6.4.0-beta.0 tag) Directive: keep the socketTimeout + reconnectStrategy pairing together; either one alone is wrong Ticket: DOC-7176 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Contributor
Contributor
🧠 Redis MemoryFound 5 related items from repository history (5 new this commit):
Memory updated at cd2bbdc |
16 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Client-side geographic failover for node-redis. This covers the experimental multi-database client (
createMultiDbClient,createMultiDbClientPool,createMultiDbCluster,createMultiDbSentinel) introduced inredis@6.4.0-beta.0. The PR also:relatedPageson the failover overviewThe page follows the redis-py and Lettuce failover pages, with node-redis-specific sections where it behaves differently:
initialAvailability: 'MAJORITY'means both endpoints in a two-endpoint setup.That last section came from testing. When a server stops responding but keeps the connection open, in-flight commands stay pending until it answers, even after the client has failed over. Only
socket.socketTimeoutrejects them. But the default reconnect strategy doesn't reconnect after a socket timeout, so the timeout has to be paired with a customreconnectStrategy, or the endpoint never fails back.Verification: every JS block on the page was extracted from the Markdown and run against
redis@6.4.0-beta.0, with tworedis:8.8containers anddocker pauseto simulate failure.LagAwareHealthCheckonly ran against unresolvable hosts, because no Redis Software cluster was available.Warning
Do not merge. These docs are written against a beta of node-redis whose multi-db API is marked
@experimentaland "may change before the stable release". Wait for a stableredis@6.4.0release — see the manifest below.Park manifest
Ticket: DOC-7176
Parked at: 2026-10-13
Trigger to pick up: a non-prerelease node-redis release (expected
redis@6.4.0) whose tag contains the multi-db merge commitec4cd0f1c75bc01e02c8bbcfaba4d73f277a62a6(PR #3435). Check withgh api 'repos/redis/node-redis/compare/ec4cd0f1c75bc01e02c8bbcfaba4d73f277a62a6...redis%406.4.0' --jq '{status, behind_by}'and expectbehind_by: 0. Also confirmnpm view redis dist-tagsshowslatestat that version.Labels: parked, do not merge yet
Pinned sources (state observed at park time)
redis@6.4.0-beta.0prerelease: true, published 2026-10-12T12:25:35Z, targetmaster, tag commit0b9915cea5164232deea7148a233f3149c38c585. npm dist-tags:beta: 6.4.0-beta.0,latest: 6.3.0. Newest non-prerelease GitHub release:redis@6.2.1.gh api repos/redis/node-redis/releases --jq '[.[] | select(.prerelease==false)][0].tag_name';npm view redis dist-tagsstate: closed,merged: true, merge SHAec4cd0f1c75bc01e02c8bbcfaba4d73f277a62a6, basemaster, updated 2026-10-09T09:02:49Zgh api repos/redis/node-redis/pulls/3435 --jq '{state, merged, merge_sha: .merge_commit_sha, base: .base.ref}'docs/multi-db.md(upstream guide)4c548d78354ad02a8082803fdbf79a4274ae8bbdat the beta taggh api 'repos/redis/node-redis/contents/docs/multi-db.md?ref=<tag>' --jq .shapackages/client/lib/multi-db/config.ts(MULTI_DB_DEFAULTS, option types)43da7b0fa82666e8ea6840368d7155f852d7ed8dpackages/client/lib/multi-db/events.ts(event map)8485c3a67783b39bae978a6854aa533cf950fff1packages/client/lib/multi-db/lag-aware-health-check.ts(options)28944e22cb4ca57ea23666766f4629a847f26c99packages/client/lib/multi-db/controller.ts(method list)f70003fc666dbe7f926d02736aa016ebb2b99b4bpackages/client/index.ts(public exports)8fe3384444fbf327906c8076772a378b2b2ca99fpackages/client/lib/client/socket.ts(defaultReconnectStrategy)afcf8e3140a036443b30a195fa062dd038b14a5f; lines 524–528 returnfalseforSocketTimeoutErrorAn unchanged blob SHA at the stable tag means that file needs no re-read.
Observed shape the page assumes
Semantics: HIGH. Run-verified against the beta. These are likely to survive to release:
{ client, controller }. The client is the event surface, and all endpoints must be the same type.CLOSEDcircuit. Ties go to the endpoint listed first.connect()is gated byinitialAvailability. A rejected firstconnect()makes the client unusable.TemporarilyUnavailableError→PermanentlyUnavailableErrorplus theterminatedevent. Callingconnect()again recovers the client.multi(), scan iterators andlegacy()are bound to the database that was active when they were created.exec()after a failover rejects withWatchErrororCommandAbandonedError.SELECT,MONITORandemitInvalidateare rejected.socketTimeoutrejects them, and the default reconnect strategy doesn't reconnect after a socket timeout.Identifiers: LOW. Read from the beta tag (location in brackets). Expect renames.
packages/client/index.ts,packages/redis/index.ts]:createMultiDbClient,createMultiDbClientPool,createMultiDbCluster,createMultiDbSentinel,defaultErrorFilter,DefaultHealthCheck,LagAwareHealthCheck,TemporarilyUnavailableError,PermanentlyUnavailableError,CommandAbandonedError,WeightBasedStrategyDatabaseConfigfields [config.ts]:id(defaultdb-<n>),options,weight(default 1, range [0,1]),skipInitialHealthCheck(addDatabaseonly),poolOptions(pool only, onPoolDatabaseConfig)config.tsMULTI_DB_DEFAULTS]:gracePeriod60000,autoFallbackInterval-1,maxFailoverAttempts10,delayBetweenFailoverAttempts12000,initialAvailability'MAJORITY'('ALL'/'MAJORITY'/'ONE'),failoverStrategy,healthCheckshealthCheck.*[config.tsHealthCheckConfig]:interval5000,timeout3000 (must be <interval),numProbes3,delayBetweenProbes500,policy'ALL'('ALL'/'MAJORITY'/'ANY')failureDetector.*[config.tsFailureDetectorConfig]:minNumOfFailures1000,failureRateThreshold10 (percent),windowSize2000,errorFilterLagAwareHealthCheckoptions [lag-aware-health-check.ts]:restEndpoint,bdbUid(each a value or(id) => value),credentials {username, password},lagTolerance5000,requestTimeout3000,requestOptions,onProbeError(err, id)health-check.ts]:probe(target)→Promise<boolean>, wheretargetis{ id, sendCommand(args) }controller.ts]:getActiveDatabase(),getDatabases()(descriptor{id, weight, circuitState, role}),addDatabase(),removeDatabase(),replaceDatabase(),setWeight(),setAutoFallback(ms | false),setActiveDatabase(),releasePin()events.ts]:connect,ready,end,terminated {attempts},error,failover {from, to, reason},fallback {from, to},database-unhealthy {id, cause},database-recovered {id},all-databases-down {attempt, maxAttempts},member-error {id, error},member-ready {id},member-end {id}reasonvalues [events.tsFailoverReason]:failure-detector,health-check,connection-ended,forced,active-removedclient/socket.ts]:socket.socketTimeout,socket.reconnectStrategy,SocketTimeoutErrorclient.duplicate()returns a{ client, controller }pair [multi-db/index.ts]Re-check checklist
npm install redis@betato the stable version and plainnpm install redis.bannerText: keep the preview banner only if the stable release still marks the multi-db API@experimental. Check the JSDoc inconfig.tsandindex.ts.MULTI_DB_DEFAULTSinconfig.tsagainst every default in the page tables, including the 120-second figure (maxFailoverAttempts×delayBetweenFailoverAttempts).defaultReconnectStrategyinsocket.ts. If it now reconnects onSocketTimeoutError, simplify "Timeouts for unresponsive servers" and the "No failback after recovery" troubleshooting item. Also check whether a multi-db fix now rejects in-flight commands on failover, which would make the section unnecessary.docs/multi-db.mdbetween the beta tag and the stable tag. Watch for changes to the behavior contracts, pinned surfaces and Pub/Sub sections.createMultiDbClientPool,createMultiDbClusterandcreateMultiDbSentinelat least once. OnlycreateMultiDbClientwas exercised. The "pools have no Pub/Sub" claim comes from upstream docs.CommandAbandonedErrorfor queued, unsent commands at failover is taken from upstream docs and wasn't reproduced. The scan-iterator andmulti()cases were reproduced.LagAwareHealthChecksuccess path is unverified because no Redis Software cluster was available. If one becomes available, run the page's example against it.docker pause.On unpark, then
Run
/unpark <this PR>when the trigger fires. The closing sequence is defined in/unparkSteps 4–5./finalizeis deferred until then, and thedo not merge yetguard holds until/finalizecompletes.🤖 Generated with Claude Code
Note
Low Risk
Documentation-only changes with no runtime or security impact; content targets a beta API and the PR is marked do-not-merge until stable release.
Overview
Adds node-redis client-side geographic failover documentation for the preview multi-database API (
createMultiDbClientand related factories inredis@6.4.0-beta.0).A new nodejs/failover page documents weighted endpoints, circuit breaker and health checks (including
LagAwareHealthCheck), runtimecontrollerAPIs, Pub/Sub re-subscription, and node-specific behavior: no command retry on failover, failback off by default,initialAvailability: 'MAJORITY'requiring both endpoints in a two-node setup, transaction/scan/WATCHsemantics, and pairingsocket.socketTimeoutwith a customreconnectStrategyfor hung connections.The shared failover overview gains a node-redis table row and related link; nodejs/produsage adds a checklist item and short geographic failover recommendation.
Reviewed by Cursor Bugbot for commit cd2bbdc. Bugbot is set up for automated code reviews on this repo. Configure here.