feat(redis): add configurable key namespace separator

This commit is contained in:
t8y2 committed 2026-06-10 17:46:48 +08:00
1 parent 14d11a9933
commit d353d4673f
20 files changed
+64 -20

No files matched your search

+2 -1
View File
@@ -1,6 +1,6 @@
use percent_encoding::{percent_decode_str, utf8_percent_encode, NON_ALPHANUMERIC};
use crate::models::connection::{ConnectionConfig, DatabaseType};
use crate::models::connection::{default_redis_key_separator, ConnectionConfig, DatabaseType};
use crate::path_utils::expand_tilde;
pub fn agent_connect_params(config: &ConnectionConfig, host: &str, port: u16, database: &str) -> serde_json::Value {
@@ -428,6 +428,7 @@ mod tests {
redis_sentinel_password: String::new(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,
+4 -1
View File
@@ -530,7 +530,9 @@ mod tests {
decrypt_sensitive_payload, encrypt_sensitive_payload, normalized_remote_path, parent_collection_paths,
scrub_connection_secrets, ConnectionSecretSnapshot, SensitiveSyncPayload,
};
use crate::models::connection::{ConnectionConfig, DatabaseType, TransportLayerConfig};
use crate::models::connection::{
default_redis_key_separator, ConnectionConfig, DatabaseType, TransportLayerConfig,
};
#[test]
fn normalizes_empty_remote_path_to_default() {
@@ -591,6 +593,7 @@ mod tests {
redis_sentinel_password: "sentinel".to_string(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,
+5 -3
View File
@@ -19,7 +19,8 @@ use crate::db::proxy_tunnel::ProxyTunnelManager;
use crate::db::ssh_tunnel::TunnelManager;
use crate::external;
use crate::models::connection::{
parse_jdbc_host_port, parse_mongo_first_host, rewrite_jdbc_url_host, ConnectionConfig, DatabaseType,
default_redis_key_separator, parse_jdbc_host_port, parse_mongo_first_host, rewrite_jdbc_url_host, ConnectionConfig,
DatabaseType,
};
use crate::path_utils::expand_tilde;
use crate::plugins::{PluginDriverSession, PluginRegistry, PluginRuntimeEnv};
@@ -1205,8 +1206,8 @@ mod tests {
use crate::agent_manager::{AgentState, JavaRuntimeConfig, JavaRuntimeMode, DEFAULT_JRE_KEY};
use crate::db;
use crate::models::connection::{
default_connect_timeout_secs, ConnectionConfig, DatabaseType, ProxyTunnelConfig, ProxyType,
TransportLayerConfig,
default_connect_timeout_secs, default_redis_key_separator, ConnectionConfig, DatabaseType, ProxyTunnelConfig,
ProxyType, TransportLayerConfig,
};
use crate::query;
use crate::schema;
@@ -1246,6 +1247,7 @@ mod tests {
redis_sentinel_password: String::new(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,
@@ -506,6 +506,7 @@ mod tests {
redis_sentinel_password: String::new(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: crate::models::connection::default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,
+16 -2
View File
@@ -60,6 +60,8 @@ pub struct ConnectionConfig {
pub redis_sentinel_tls: bool,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub redis_cluster_nodes: String,
#[serde(default = "default_redis_key_separator", skip_serializing_if = "is_default_redis_separator")]
pub redis_key_separator: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub etcd_endpoints: String,
/// Typed configuration for external tabular sources.
@@ -196,6 +198,14 @@ fn is_false(value: &bool) -> bool {
!*value
}
pub fn default_redis_key_separator() -> String {
":".to_string()
}
fn is_default_redis_separator(value: &str) -> bool {
value == ":"
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
@@ -337,6 +347,8 @@ struct ConnectionConfigData {
pub redis_sentinel_tls: bool,
#[serde(default)]
pub redis_cluster_nodes: String,
#[serde(default = "default_redis_key_separator")]
pub redis_key_separator: String,
#[serde(default)]
pub etcd_endpoints: String,
#[serde(default)]
@@ -386,6 +398,7 @@ impl From<ConnectionConfigData> for ConnectionConfig {
redis_sentinel_password: data.redis_sentinel_password,
redis_sentinel_tls: data.redis_sentinel_tls,
redis_cluster_nodes: data.redis_cluster_nodes,
redis_key_separator: data.redis_key_separator,
etcd_endpoints: data.etcd_endpoints,
external_config: data.external_config,
jdbc_driver_class: data.jdbc_driver_class,
@@ -1337,8 +1350,8 @@ fn bracket_ipv6(host: &str) -> String {
#[cfg(test)]
mod tests {
use super::{
default_query_timeout_secs, default_ssh_connect_timeout_secs, ConnectionConfig, DatabaseType,
ProxyTunnelConfig, ProxyType, TransportLayerConfig,
default_query_timeout_secs, default_redis_key_separator, default_ssh_connect_timeout_secs, ConnectionConfig,
DatabaseType, ProxyTunnelConfig, ProxyType, TransportLayerConfig,
};
use std::str::FromStr;
@@ -1376,6 +1389,7 @@ mod tests {
redis_sentinel_password: String::new(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,
+2 -1
View File
@@ -8,7 +8,7 @@ use tokio_util::sync::CancellationToken;
use crate::connection::{AppState, PoolKind};
use crate::db;
use crate::models::connection::DatabaseType;
use crate::models::connection::{default_redis_key_separator, DatabaseType};
use crate::sql::{split_sql_batches, split_sql_statements, starts_with_duckdb_result_sql_keyword};
pub const QUERY_TIMEOUT: Duration = Duration::from_secs(30);
@@ -1848,6 +1848,7 @@ mod tests {
redis_sentinel_password: String::new(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,
+3 -2
View File
@@ -1,6 +1,6 @@
use crate::connection::{connection_url_for_endpoint, database_connection_config, AppState, MysqlMode, PoolKind};
use crate::db;
use crate::models::connection::{ConnectionConfig, DatabaseType};
use crate::models::connection::{default_redis_key_separator, ConnectionConfig, DatabaseType};
use crate::query::{agent_execute_query_params, QueryExecutionOptions};
use std::collections::HashSet;
use std::future::Future;
@@ -614,7 +614,7 @@ mod tests {
duckdb_query_tables_in_database, filter_objects_by_types, filter_yashandb_recyclebin_objects,
filter_yashandb_recyclebin_tables, is_agent_postgres_metadata_fallback_config,
};
use crate::models::connection::{ConnectionConfig, DatabaseType};
use crate::models::connection::{default_redis_key_separator, ConnectionConfig, DatabaseType};
fn test_column(name: &str, comment: Option<&str>, is_primary_key: bool) -> super::db::ColumnInfo {
super::db::ColumnInfo {
@@ -665,6 +665,7 @@ mod tests {
redis_sentinel_password: String::new(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,
+2 -1
View File
@@ -6,7 +6,7 @@ use tokio::sync::RwLock;
use crate::connection::{AppState, PoolKind};
use crate::db;
use crate::db::mongo_driver::MongoDocumentResult;
use crate::models::connection::DatabaseType;
use crate::models::connection::{default_redis_key_separator, DatabaseType};
use crate::object_source_sql::{build_executable_object_source_statements, EditableObjectSourceSqlInput};
use crate::query::{agent_execute_query_params, QueryExecutionOptions};
use crate::sql::starts_with_executable_sql_keyword;
@@ -3161,6 +3161,7 @@ mod tests {
redis_sentinel_password: String::new(),
redis_sentinel_tls: false,
redis_cluster_nodes: String::new(),
redis_key_separator: default_redis_key_separator(),
etcd_endpoints: String::new(),
external_config: None,
jdbc_driver_class: None,