Skip to main content

glide/config/
standalone.rs

1// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
2//! Configuration for the **standalone** (non-cluster) client.
3
4use super::common::{
5    BackoffStrategy, ClientIdentity, NodeAddress, NodeDiscoveryMode, ProtocolVersion,
6    PubSubSubscriptions, ReadFrom, ServerCredentials, TlsConfig, credentials_from_info,
7    duration_as_millis_u32, from_redis_protocol, impl_common_config_builders,
8    split_connection_addr, to_redis_connection_info,
9};
10use glide_core::client::ConnectionRequest;
11use std::time::Duration;
12
13/// Configuration for a **standalone** (non-cluster) GLIDE client.
14#[derive(Debug, Clone)]
15#[non_exhaustive]
16pub struct GlideClientConfiguration {
17    /// Seed node addresses.
18    pub addresses: Vec<NodeAddress>,
19    /// TLS mode.
20    pub tls: TlsConfig,
21    /// Optional credentials.
22    pub credentials: Option<ServerCredentials>,
23    /// Read strategy.
24    pub read_from: ReadFrom,
25    /// How the client discovers node roles and topology.
26    pub node_discovery_mode: NodeDiscoveryMode,
27    /// Overall request timeout.
28    pub request_timeout: Option<Duration>,
29    /// Connection establishment timeout.
30    pub connection_timeout: Option<Duration>,
31    /// Reconnection backoff strategy.
32    pub reconnect_strategy: Option<BackoffStrategy>,
33    /// Logical database index to SELECT on connect.
34    pub database_id: i64,
35    /// Client name reported to the server (`CLIENT SETNAME`).
36    pub client_name: Option<String>,
37    /// RESP protocol version.
38    pub protocol: ProtocolVersion,
39    /// Maximum number of concurrent in-flight requests.
40    pub inflight_requests_limit: Option<u32>,
41    /// Defer connecting until the first command is issued.
42    pub lazy_connect: bool,
43    /// Pub/Sub subscriptions to establish on connect.
44    pub pubsub_subscriptions: Option<PubSubSubscriptions>,
45    /// Force creation of the Pub/Sub push channel even when no subscriptions are
46    /// configured, so runtime `subscribe`/`unsubscribe` can receive messages.
47    /// See [`crate::commands::pubsub::PubSubCommands`].
48    pub force_pubsub_channel: bool,
49    /// Custom CA certificate(s) (PEM bytes) to trust when verifying the server
50    /// under [`TlsConfig::SecureTls`]. Lowered into
51    /// `ConnectionRequest::root_certs`. Empty = use the system trust store.
52    pub root_certs: Vec<Vec<u8>>,
53    /// Client certificate + private key for **mutual TLS**. Set via
54    /// [`Self::client_identity`]. Only meaningful together with
55    /// [`TlsConfig::SecureTls`].
56    pub client_identity: Option<ClientIdentity>,
57}
58
59impl_common_config_builders!(GlideClientConfiguration);
60
61impl GlideClientConfiguration {
62    /// Create a standalone configuration for the given addresses.
63    pub fn new(addresses: Vec<NodeAddress>) -> Self {
64        GlideClientConfiguration {
65            addresses,
66            tls: TlsConfig::NoTls,
67            credentials: None,
68            read_from: ReadFrom::Primary,
69            node_discovery_mode: NodeDiscoveryMode::Standard,
70            request_timeout: None,
71            connection_timeout: None,
72            reconnect_strategy: None,
73            database_id: 0,
74            client_name: None,
75            protocol: ProtocolVersion::default(),
76            inflight_requests_limit: None,
77            lazy_connect: false,
78            pubsub_subscriptions: None,
79            force_pubsub_channel: false,
80            root_certs: Vec::new(),
81            client_identity: None,
82        }
83    }
84
85    /// Build a configuration from a connection URL.
86    ///
87    /// Supports Redis URLs:
88    ///
89    /// ```
90    /// use glide::GlideClientConfiguration;
91    /// let url = "redis://user:pass@localhost:6379/2";
92    /// let cfg = GlideClientConfiguration::from_url(url).unwrap();
93    /// assert_eq!(cfg.database_id, 2);
94    /// ```
95    ///
96    /// `rediss://` enables TLS with full verification;
97    /// `rediss://…/#insecure` disables certificate verification.
98    ///
99    /// Does not support Unix-socket URLs (`unix://` or `unix+redis://`).
100    /// Does not support Valkey URLs (`valkey://` or `valkeys://`).
101    // TODO #7031: Accept `valkey://` and `valkeys://` schemes.
102    pub fn from_url(url: impl AsRef<str>) -> crate::ValkeyResult<Self> {
103        let info = to_redis_connection_info(url)?;
104        let (address, tls) = split_connection_addr(info.addr)?;
105
106        let mut cfg = Self::new(vec![address]).tls(tls);
107        cfg.database_id = info.redis.db;
108        cfg.protocol = from_redis_protocol(info.redis.protocol);
109        cfg.client_name = info.redis.client_name;
110        cfg.credentials = credentials_from_info(info.redis.username, info.redis.password);
111
112        Ok(cfg)
113    }
114
115    /// Set database id.
116    pub fn database_id(mut self, db: i64) -> Self {
117        self.database_id = db;
118        self
119    }
120
121    /// Set how the client discovers node roles and topology.
122    pub fn node_discovery_mode(mut self, mode: NodeDiscoveryMode) -> Self {
123        self.node_discovery_mode = mode;
124        self
125    }
126
127    pub(crate) fn to_request(&self) -> ConnectionRequest {
128        let mut req = self.common_request();
129        req.cluster_mode_enabled = false;
130        req.database_id = self.database_id;
131        req.node_discovery_mode = self.node_discovery_mode.to_core();
132        req
133    }
134}