feat(connection): show server versions for more datasources

This commit is contained in:
二丫讲梵 authored and GitHub committed 2026-08-26 18:29:13 +08:00
1 parent fb907a5866
commit 25ea7b21eb
20 files changed
+408 -38

No files matched your search

+93 -21
View File
@@ -1024,17 +1024,30 @@ async fn test_redis_connection(
host: &str,
port: u16,
connect_timeout: std::time::Duration,
) -> Result<String, String> {
) -> Result<Option<DatabaseConnectionInfo>, String> {
// Connection tests must exercise the same Redis lifecycle as a saved connection,
// including compatibility auth, TLS, and database selection.
if config.uses_redis_cluster() {
drop(state.connect_redis_cluster(tunnel_id, config).await?);
} else if config.uses_redis_sentinel() {
drop(state.connect_redis_sentinel(tunnel_id, config).await?);
} else {
drop(db::redis_driver::connect_standalone(config, host, port, connect_timeout).await?);
let connection =
db::redis_driver::RedisConnection::Cluster(state.connect_redis_cluster(tunnel_id, config).await?);
let info = db::redis_driver::database_connection_info(&connection).await.ok();
drop(connection);
return Ok(info);
}
Ok("Connection successful".to_string())
if config.uses_redis_sentinel() {
let connection = db::redis_driver::RedisConnection::Direct(tokio::sync::Mutex::new(
state.connect_redis_sentinel(tunnel_id, config).await?,
));
let info = db::redis_driver::database_connection_info(&connection).await.ok();
drop(connection);
return Ok(info);
}
let connection = db::redis_driver::RedisConnection::Direct(tokio::sync::Mutex::new(
db::redis_driver::connect_standalone(config, host, port, connect_timeout).await?,
));
let info = db::redis_driver::database_connection_info(&connection).await.ok();
drop(connection);
Ok(info)
}
#[tauri::command]
@@ -1173,7 +1186,13 @@ async fn test_connection_with_info_inner(
DatabaseType::Redis => {
// Keep the result inside the outer lifecycle so temporary transports
// are reset after both successful and failed Redis tests.
test_redis_connection(state, &tunnel_id, &config, &host, port, connect_timeout).await
match test_redis_connection(state, &tunnel_id, &config, &host, port, connect_timeout).await {
Ok(info) => {
database_info = info;
Ok("Connection successful".to_string())
}
Err(error) => Err(error),
}
}
#[cfg(feature = "duckdb-sidecar")]
DatabaseType::DuckDb => {
@@ -1191,8 +1210,19 @@ async fn test_connection_with_info_inner(
.connect(mongo_legacy_connect_params(&config, &host, port)?)
.await
.map_err(|err| mongo_legacy_error_with_auth_hint(&err))?;
let version = client
.mongo_server_version::<String>(config.effective_database().unwrap_or("admin"))
.await
.ok();
client.disconnect().await.ok();
return Ok(ConnectionTestResult::success("Connection successful (via legacy driver)"));
return Ok(ConnectionTestResult::success("Connection successful (via legacy driver)")
.with_database_info(version.map(|product_version| DatabaseConnectionInfo {
product_name: Some("MongoDB".to_string()),
product_version: Some(product_version),
current_database: config.effective_database().map(str::to_string),
driver_name: Some("MongoDB legacy Agent".to_string()),
..Default::default()
})));
}
let native_err = match db::mongo_driver::connect_with_oidc(
@@ -1212,7 +1242,15 @@ async fn test_connection_with_info_inner(
)
.await
{
Ok(()) => return Ok(ConnectionTestResult::success("Connection successful")),
Ok(()) => {
let info =
db::mongo_driver::database_connection_info(&client, config.effective_database())
.await
.ok();
return Ok(
ConnectionTestResult::success("Connection successful").with_database_info(info)
);
}
Err(e) => e,
}
}
@@ -1228,7 +1266,18 @@ async fn test_connection_with_info_inner(
&mongo_legacy_error_with_auth_hint(&err),
)
})?;
let version = client
.mongo_server_version::<String>(config.effective_database().unwrap_or("admin"))
.await
.ok();
client.disconnect().await.ok();
database_info = version.map(|product_version| DatabaseConnectionInfo {
product_name: Some("MongoDB".to_string()),
product_version: Some(product_version),
current_database: config.effective_database().map(str::to_string),
driver_name: Some("MongoDB legacy Agent".to_string()),
..Default::default()
});
Ok("Connection successful (via legacy driver)".to_string())
} else {
Err(native_err)
@@ -1301,9 +1350,9 @@ async fn test_connection_with_info_inner(
config.external_config.as_ref(),
connect_timeout,
)?;
db::meilisearch_driver::test_connection(&client, connect_timeout)
.await
.map(|_| "Connection successful".to_string())
db::meilisearch_driver::test_connection(&client, connect_timeout).await?;
database_info = db::meilisearch_driver::database_connection_info(&client).await.ok();
Ok("Connection successful".to_string())
}
DatabaseType::Hbase => {
let client = db::hbase_driver::HBaseClient::new(
@@ -1313,9 +1362,9 @@ async fn test_connection_with_info_inner(
false,
connect_timeout,
)?;
db::hbase_driver::test_connection(&client, connect_timeout)
.await
.map(|_| "Connection successful".to_string())
db::hbase_driver::test_connection(&client, connect_timeout).await?;
database_info = db::hbase_driver::database_connection_info(&client).await.ok().flatten();
Ok("Connection successful".to_string())
}
DatabaseType::Qdrant | DatabaseType::Milvus | DatabaseType::Weaviate | DatabaseType::ChromaDb => {
let kind = match config.db_type {
@@ -1388,14 +1437,16 @@ async fn test_connection_with_info_inner(
DatabaseType::VictoriaMetrics => {
let client =
db::victoriametrics_driver::VictoriaMetricsClient::new_for_config(&url, &config, connect_timeout)?;
db::victoriametrics_driver::test_connection(&client, connect_timeout)
.await
.map(|_| "Connection successful".to_string())
db::victoriametrics_driver::test_connection(&client, connect_timeout).await?;
database_info =
db::victoriametrics_driver::database_connection_info(&client, connect_timeout).await.ok();
Ok("Connection successful".to_string())
}
DatabaseType::Nacos => {
let admin_config = state.nacos_admin_config_for_connection(connection_id, &config).await?;
let adapter = state.nacos_registry.build_transient_config(admin_config).await?;
adapter.test_connection_with_scope_validation().await?;
let info = adapter.test_connection_with_scope_validation().await?;
database_info = dbx_core::nacos::service::database_info_from_connection(&info);
Ok("Connection successful".to_string())
}
DatabaseType::Consul => {
@@ -1413,6 +1464,13 @@ async fn test_connection_with_info_inner(
} else {
client.agent_self().await.ok()
};
database_info = identity.as_ref().map(|identity| DatabaseConnectionInfo {
product_name: Some("Consul".to_string()),
product_version: identity.version.clone(),
server_comment: Some(format!("Agent {}", identity.node)),
driver_name: Some("Consul HTTP API".to_string()),
..Default::default()
});
Ok(identity
.map(|identity| format!("Connection successful (Agent: {} at {})", identity.node, identity.address))
.unwrap_or_else(|| {
@@ -1426,7 +1484,21 @@ async fn test_connection_with_info_inner(
let mqc = state.mq_admin_config_for_connection(connection_id, &config).await?;
let agent_launch = dbx_core::mq::service::resolve_mq_agent_launch_spec(&mqc, state);
let adapter = state.mq_registry.build_transient_config(mqc, agent_launch).await?;
adapter.test_connection().await?;
let info = adapter.test_connection().await?;
database_info = Some(DatabaseConnectionInfo {
product_name: Some(
match info.system_kind {
dbx_core::mq::types::MqSystemKind::Pulsar => "Pulsar",
dbx_core::mq::types::MqSystemKind::Kafka => "Kafka",
dbx_core::mq::types::MqSystemKind::RocketMq => "RocketMQ",
dbx_core::mq::types::MqSystemKind::RabbitMq => "RabbitMQ",
}
.to_string(),
),
product_version: info.server_version,
driver_name: Some("Message Queue Admin API".to_string()),
..Default::default()
});
Ok("Connection successful".to_string())
}
#[cfg(not(feature = "mq-admin"))]