Skip to content

Catchup to upstream - #2

Open
Bernie wants to merge 60 commits into
Bernie:masterfrom
braze-inc:catchup_to_upstream
Open

Catchup to upstream#2
Bernie wants to merge 60 commits into
Bernie:masterfrom
braze-inc:catchup_to_upstream

Conversation

@Bernie

@Bernie Bernie commented Aug 13, 2026

Copy link
Copy Markdown
Owner

This just catches our master up to the upstream.

supercaracal and others added 30 commits December 20, 2025 13:16
…hRing

Ref: rails/rails#57004
Ref: redis-rb/redis-client#292

I'm working on a big cleanup of Rails `RedisCacheStore` and it needs to
support consistent hashing, which I did add in `redis-client` `0.28.0`.

For Rails users to be able to use a redis cluster as a cache store,
`redis-cluster-client` would need to have a shim for the now base
interface:

  - `with`
  - `nodes`
  - `node_for`
  - `nodes_for`
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Fix typos (metdata, hashag, guaranted, transction, fhe, GItHub),
grammar issues (missing verbs, wrong verb forms, uncountable nouns),
and Japanese-English patterns (upper libraries, works multiple keys,
recommend to use, the followings, etc.) across README.md and source comments.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mplementation

- class_diagrams_redis_cluster_client.md:
  - RedisClient::Cluster: add multi() and with()
  - RedisClient::ClusterConfig: replace obsolete per_node_key/update_node/add_node/dup
    with client_config_for_node, resolved?, sentinel?, server_url, and timeout readers
  - RedisClient::Cluster::Command: add exists?()
  - RedisClient::Cluster::Node: remove non-existent self.load_info(), add try_reload!,
    clients, primary_clients, replica_clients
  - Add RedisClient::Cluster::Node::BaseTopology class
  - Add RedisClient::Cluster::Node::RandomReplicaOrPrimary class (was missing)
  - Remove module_RedisClient_Cluster_Node_ReplicaMixin (no longer exists)
  - Update topology class relationships to use inheritance from BaseTopology
  - RedisClient::Cluster::Router: remove non-existent try_send(), add all current
    public methods (handle_redirection, scan_single_key, find_node_key_by_key, etc.)
  - Add RedisClient::Cluster::OptimisticLocking class and its relationships
  - module_RedisClient_Cluster_NodeKey: add build_from_client()

- class_diagrams_redis_client.md:
  - RedisClient: add self.ring, self.now, self.now_ms, server_url, db, host, port,
    path, username, password, idle_timeout, disable_reconnection, measure_round_trip_delay
  - module_RedisClient_Common: add nodes, node_for, nodes_for
  - module_RedisClient_Config_Common: add idle_timeout, protocol, circuit_breaker,
    custom, inherit_socket, driver_info, middlewares_stack, resolved?, server_url,
    build_lib_name
  - RedisClient::SentinelConfig: add resolved?
  - RedisClient::RubyConnection: add measure_round_trip_delay

- sequence_diagrams.md:
  - Update initial topology fetch from CLUSTER NODES to CLUSTER SHARDS
    (with fallback note for older Redis versions)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
supercaracal and others added 29 commits August 13, 2026 10:02
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClusterConfig#inspect previously dumped startup_nodes hashes which
contained raw :username and :password values, leaking them into logs,
exception messages, IRB output, APM traces, etc.

Replace sensitive values with '[FILTERED]' before constructing the
inspect string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nError

The retry counter in handle_redirection used [times_block_executed, 1].min,
which deducts 0 when the inner block never executed (e.g., when initial
node lookup or pre-block code in Router#handle_redirection raises). The
inline comment said "Always deduct at least one"; the code did the
opposite. Persistent ConnectionError on the WATCH path could spin without
ever decrementing retry_count.

Switching to .max matches the documented intent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NodeKey.split previously used rindex(':') to separate host from
port. This works for bracket-less IPv6 ('::1:6379') but leaves
the brackets attached for the standard URL form ('[::1]:6379'),
producing a host '[::1]' that downstream connection code cannot
resolve.

Detect the [host]:port form explicitly and strip the brackets.
The legacy bracket-less path is preserved unchanged.

build_from_host_port is intentionally left as-is in this PR;
changing the produced NodeKey format has cluster-wide implications
and belongs in a separate change.
PubSub#@commands logged every command and was replayed in start_over
on reconnect. Subscribe entries for channels the user later
unsubscribed from were never removed, so long-lived clients
accumulated unbounded memory and replays were O(history) instead
of O(active subscriptions).

Track only the active subscription set: subscribe-family commands
are appended; unsubscribe-family commands prune matching entries
(by command type and channel list) and are not themselves stored.
Pipeline#execute previously raised v.first_exception eagerly on the
first node-batch that carried one, dropping redirection processing
and cluster_state_errors processing for all remaining batches.

Defer the raise until after all batches have been processed; preserve
the original "raise the first encountered exception" semantics so the
exception type seen by the caller is unchanged.
Some managed Redis services (e.g. AWS ElastiCache Serverless) report
`127.0.0.1` in the `ip` field of `CLUSTER SHARDS` while exposing the
real, reachable address only via `endpoint` / `hostname`. Building
node_keys from `ip` then yields an unreachable topology and the
client fails on the next operation that walks all nodes (e.g.
`SCAN`/`delete_matched`) with:

    Connection refused - connect(2) for 127.0.0.1:6379

This regressed in v0.16.0 (redis-rb#479) when topology discovery switched
from `CLUSTER NODES` to `CLUSTER SHARDS`; redis-rb#207 had previously
established hostname precedence for the `CLUSTER NODES` path.

`parse_cluster_shards_reply` now picks the host using:

  1. `endpoint` (server-selected per `cluster-preferred-endpoint-type`)
  2. `hostname` (when `endpoint` is absent or `?`)
  3. `ip` (fallback)

mirroring the precedence used by `parse_node_key` for CLUSTER NODES.

Refs: redis-rb#515
@Bernie
Bernie force-pushed the catchup_to_upstream branch from 61613a0 to cd950a0 Compare August 13, 2026 14:53
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.

4 participants