Skip to content

Commit 6f96c84

Browse files
CORE: Track HELLO and AUTH state for reconnection (#5145)
- Add update_username() and update_protocol() methods to Client for persisting authentication state - Add update_connection_username() and update_connection_protocol() methods to ClusterConnection for cluster-wide state updates - Add UpdateConnectionUsername and UpdateConnectionProtocol operations to cluster routing - Reclassify AUTH command as write operation in cluster routing to ensure state is tracked across all nodes - Update CHANGELOG.md to document HELLO and AUTH state tracking feature - Ensure reconnections preserve protocol version and username from previous successful connections Signed-off-by: affonsov <67347924+affonsov@users.noreply.github.com> Co-authored-by: Pratheep Kumar <pratheepkumar0403@gmail.com>
1 parent f20ce2c commit 6f96c84

File tree

8 files changed

+812
-3
lines changed

8 files changed

+812
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* Python: Move OpenTelemetry config classes to glide_shared for code reuse between async and sync clients
2121
* JAVA: Add dynamic PubSub methods (subscribe, psubscribe, unsubscribe, punsubscribe, ssubscribe, sunsubscribe), getSubscriptions() for subscription state tracking, pubsubReconciliationIntervalMs configuration option, and subscription_out_of_sync_count and subscription_last_sync_timestamp metrics ([#5267](https://github.com/valkey-io/valkey-glide/issues/5267))
2222
* Go: Add ALLOW_NON_COVERED_SLOTS flag support for cluster scan ([#4895](https://github.com/valkey-io/valkey-glide/issues/4895))
23+
* CORE: Track HELLO and AUTH state for reconnection ([#5145](https://github.com/valkey-io/valkey-glide/issues/5145))
2324

2425
#### Fixes
2526
* Node: Fix to handle non-string types in toBuffersArray ([#4842](https://github.com/valkey-io/valkey-glide/issues/4842))

glide-core/redis-rs/redis/src/client.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
connection::{connect, Connection, ConnectionInfo, ConnectionLike, IntoConnectionInfo},
88
push_manager::PushInfo,
99
retry_strategies::RetryStrategy,
10-
types::{RedisResult, Value},
10+
types::{ProtocolVersion, RedisResult, Value},
1111
};
1212
#[cfg(feature = "aio")]
1313
use std::net::IpAddr;
@@ -602,6 +602,34 @@ impl Client {
602602
pub fn update_client_name(&mut self, client_name: Option<String>) {
603603
self.connection_info.redis.client_name = client_name;
604604
}
605+
606+
/// Updates the username in connection_info.
607+
///
608+
/// This method updates the username field in the connection information,
609+
/// which will be used for subsequent connections and reconnections.
610+
/// Typically updated when AUTH command is used with a username.
611+
///
612+
/// # Arguments
613+
///
614+
/// * `username` - The username to use for authentication (None to clear)
615+
///
616+
pub fn update_username(&mut self, username: Option<String>) {
617+
self.connection_info.redis.username = username;
618+
}
619+
620+
/// Updates the protocol version in connection_info.
621+
///
622+
/// This method updates the protocol field in the connection information,
623+
/// which will be used for subsequent connections and reconnections.
624+
/// Typically updated when HELLO command is used to change protocol version.
625+
///
626+
/// # Arguments
627+
///
628+
/// * `protocol` - The protocol version to use (RESP2 or RESP3)
629+
///
630+
pub fn update_protocol(&mut self, protocol: ProtocolVersion) {
631+
self.connection_info.redis.protocol = protocol;
632+
}
605633
}
606634

607635
#[cfg(feature = "aio")]

glide-core/redis-rs/redis/src/cluster_async/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ use crate::{
8585
self, MultipleNodeRoutingInfo, Redirect, ResponsePolicy, Route, SingleNodeRoutingInfo,
8686
},
8787
push_manager::PushInfo,
88+
types::ProtocolVersion,
8889
Cmd, ConnectionInfo, ErrorKind, IntoConnectionInfo, RedisError, RedisFuture, RedisResult,
8990
Value,
9091
};
@@ -356,6 +357,40 @@ where
356357
.await
357358
}
358359

360+
/// Update the username used to authenticate with all cluster servers
361+
///
362+
/// This method updates the username for all cluster connections and stores it for future reconnections.
363+
/// Typically called after a successful AUTH command with a username parameter.
364+
///
365+
/// # Arguments
366+
///
367+
/// * `username` - The username to use for authentication (None to clear)
368+
///
369+
pub async fn update_connection_username(
370+
&mut self,
371+
username: Option<String>,
372+
) -> RedisResult<Value> {
373+
self.route_operation_request(Operation::UpdateConnectionUsername(username))
374+
.await
375+
}
376+
377+
/// Update the protocol version used for all cluster connections
378+
///
379+
/// This method updates the protocol version for all cluster connections and stores it for future reconnections.
380+
/// Typically called after a successful HELLO command that changes the protocol version.
381+
///
382+
/// # Arguments
383+
///
384+
/// * `protocol` - The protocol version to use (RESP2 or RESP3)
385+
///
386+
pub async fn update_connection_protocol(
387+
&mut self,
388+
protocol: ProtocolVersion,
389+
) -> RedisResult<Value> {
390+
self.route_operation_request(Operation::UpdateConnectionProtocol(protocol))
391+
.await
392+
}
393+
359394
/// Get the username used to authenticate with all cluster servers
360395
pub async fn get_username(&mut self) -> RedisResult<Value> {
361396
self.route_operation_request(Operation::GetUsername).await
@@ -683,6 +718,8 @@ enum Operation {
683718
UpdateConnectionPassword(Option<String>),
684719
UpdateConnectionDatabase(i64),
685720
UpdateConnectionClientName(Option<String>),
721+
UpdateConnectionUsername(Option<String>),
722+
UpdateConnectionProtocol(ProtocolVersion),
686723
GetUsername,
687724
}
688725

@@ -2621,6 +2658,16 @@ where
26212658
.expect(MUTEX_WRITE_ERR);
26222659
Ok(Response::Single(Value::Okay))
26232660
}
2661+
Operation::UpdateConnectionUsername(username) => {
2662+
core.set_cluster_param(|params| params.username = username)
2663+
.expect(MUTEX_WRITE_ERR);
2664+
Ok(Response::Single(Value::Okay))
2665+
}
2666+
Operation::UpdateConnectionProtocol(protocol) => {
2667+
core.set_cluster_param(|params| params.protocol = protocol)
2668+
.expect(MUTEX_WRITE_ERR);
2669+
Ok(Response::Single(Value::Okay))
2670+
}
26242671
Operation::GetUsername => {
26252672
let username = match core
26262673
.get_cluster_param(|params| params.username.clone())

glide-core/redis-rs/redis/src/cluster_routing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ impl ResponsePolicy {
595595

596596
b"WAITAOF" => Some(ResponsePolicy::AggregateArray(ArrayAggregateOp::Min)),
597597

598-
b"ACL SETUSER" | b"ACL DELUSER" | b"ACL SAVE" | b"CLIENT SETNAME"
598+
b"ACL SETUSER" | b"ACL DELUSER" | b"ACL SAVE" | b"AUTH" | b"CLIENT SETNAME"
599599
| b"CLIENT SETINFO" | b"CONFIG SET" | b"CONFIG RESETSTAT" | b"CONFIG REWRITE"
600600
| b"FLUSHALL" | b"FLUSHDB" | b"FUNCTION DELETE" | b"FUNCTION FLUSH"
601601
| b"FUNCTION LOAD" | b"FUNCTION RESTORE" | b"MEMORY PURGE" | b"MSET" | b"JSON.MSET"
@@ -654,6 +654,7 @@ fn base_routing(cmd: &[u8]) -> RouteBy {
654654
b"ACL SETUSER"
655655
| b"ACL DELUSER"
656656
| b"ACL SAVE"
657+
| b"AUTH"
657658
| b"CLIENT SETNAME"
658659
| b"CLIENT SETINFO"
659660
| b"SELECT"
@@ -750,7 +751,6 @@ fn base_routing(cmd: &[u8]) -> RouteBy {
750751
| b"ACL LOG"
751752
| b"ACL USERS"
752753
| b"ACL WHOAMI"
753-
| b"AUTH"
754754
| b"BGSAVE"
755755
| b"CLIENT GETNAME"
756756
| b"CLIENT GETREDIR"

0 commit comments

Comments
 (0)