Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## unstable #15888 +/- ##
============================================
- Coverage 77.73% 77.58% -0.15%
============================================
Files 146 146
Lines 88012 88016 +4
============================================
- Hits 68412 68291 -121
- Misses 19600 19725 +125 🚀 New features to boost your workflow:
|
|
|
||
| if (reconnect_proto == RESP_PROTO_NONE && (!config.resp3 || config.resp2)) return REDIS_OK; | ||
| if (reconnect_proto == RESP_PROTO_NONE) proto = RESP_PROTO_3; | ||
|
|
There was a problem hiding this comment.
reconnect_proto is computed inside cliConnect() itself, gated only on flags & CC_FORCE. CC_FORCE is passed by five different call sites ( ours, cliReadReply()'s blocking-abort path, the explicit connect <host> <port> command, Ctrl+C-out-of-pubsub, and the Lua debugger restart) . Since cliConnect() has no way to tell which of those triggered it, this now also applies to connect <host> <port>:: if you're on RESP3 talking to server A and explicitly run connect B 6380, this would silently try to carry RESP3 over to B too, even though that's a deliberate switch to an unrelated server. for example: 127.0.0.1:6400> HELLO 3
1# "server" => "redis"
2# "version" => "255.255.255"
3# "proto" => (integer) 3
4# "id" => (integer) 4
5# "mode" => "standalone"
6# "role" => "master"
7# "modules" =>
- 1# "name" => "vectorset"
2# "ver" => (integer) 1
3# "path" => ""
4# "args" => (empty array)
127.0.0.1:6400>
127.0.0.1:6400>
127.0.0.1:6400> CLIENT INFO
id=4 addr=127.0.0.1:44150 laddr=127.0.0.1:6400 fd=12 name= age=11 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=26 qbuf-free=20448 argv-mem=10 multi-mem=0 rbs=1024 rbp=0 obl=0 oll=0 omem=0 omem-shared=0 omem-unshared=0 tot-mem=22810 events=r cmd=client|info user=default redir=-1 resp=3 lib-name= lib-ver= io-thread=0 tot-net-in=75 tot-net-out=268174 tot-cmds=2 read-events=3 avg-pipeline-len-sum=3 avg-pipeline-len-cnt=3
127.0.0.1:6400> connect 127.0.0.1 6401
127.0.0.1:6401>
127.0.0.1:6401> CLIENT INFO
id=4 addr=127.0.0.1:39098 laddr=127.0.0.1:6401 fd=12 name= age=3 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=26 qbuf-free=20448 argv-mem=10 multi-mem=0 rbs=1024 rbp=0 obl=0 oll=0 omem=0 omem-shared=0 omem-unshared=0 tot-mem=22810 events=r cmd=client|info user=default redir=-1 resp=3 lib-name= lib-ver= io-thread=0 tot-net-in=48 tot-net-out=223 tot-cmds=1 read-events=2 avg-pipeline-len-sum=2 avg-pipeline-len-cnt=2
127.0.0.1:6401>
I scoped the original fix to only the redirect/dropped-connection reconnect specifically to avoid that. wdyt?
There was a problem hiding this comment.
You're right. CC_FORCE is shared by automatic reconnects and the interactive connect command, so cliConnect() cannot determine whether the previous protocol should be restored.
I kept protocol restoration in cliConnect() for automatic reconnects, but reset config.current_resp to RESP_PROTO_NONE in the explicit connect path before calling cliConnect(CC_FORCE).
This makes an explicit connection to a new target start with that target's default or startup-selected protocol. It also prevents a failed first connection from carrying the previous target's protocol into a later retry.
I added tests for both a successful explicit switch and a failed switch followed by a retry. The retry test verifies that the final connection is to the new server and uses RESP
There was a problem hiding this comment.
Thanks for the valuable feedback looking forward to your further insights
There was a problem hiding this comment.
Thanks, I revisited #15806 and agree that protocol restoration should remain scoped to the dropped-connection/cluster reissue path in issueCommandRepeat(). Moving it into cliConnect() would affect every CC_FORCE caller, including explicit connect and the blocking, monitor, and pub/sub cancellation paths, by replaying the previous protocol. My earlier reply was inaccurate.
I’ve removed all redis-cli.c changes, so this PR is now test-only.
The daily failure is a test-environment mismatch. The reply-schemas-validator job runs with --force-resp3, the test is intended to run against a RESP2-default server, so I now skip it when --force-resp3 is enabled.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Reviewed by Cursor Bugbot for commit 3893b50. Configure here.

Issue
The Daily
reply-schemas-validatorjob fails in the testInteractive CLI: explicit HELLO 2 downgrade is not silently reverted by a later reconnect: https://github.com/redis/redis/actions/runs/36502067759/job/109194987787After the reconnect,
CLIENT INFOshowsresp=3. This test was added in #15806.The job runs with
--force-resp3, and PR CI does not use this flag, so the failure only appears in Daily.Change
Skip this test when
$::force_resp3is set. Keep the test body and theresp=2check as they are, so the default run still checks that the one-shot upgrade does not undo an explicitHELLO 2.Note
Low Risk
Test harness gating only; no production code in this diff.
Overview
The explicit HELLO 2 downgrade / reconnect interactive test in
redis-cli.tclis now wrapped inif {!$::force_resp3}so it does not run when the suite is started with--force-resp3(e.g. reply-schema CI).That run mode keeps clients on RESP3, so exercising an intentional downgrade to RESP2 and asserting
CLIENT INFOstill showsresp=2after a forced reconnect would be invalid and was failing daily CI. The existing RESP3 persists across reconnect test remains unconditional.Reviewed by Cursor Bugbot for commit cfa40ca. Bugbot is set up for automated code reviews on this repo. Configure here.