fix(mongodb): install legacy agent before automatic fallback

Closes #6167
This commit is contained in:
t8y2 committed 2026-08-14 16:02:42 +00:00
1 parent 3a637de44c
commit 86bb88ab66
4 files changed
+336 -15

No files matched your search

+69 -12
View File
@@ -14,7 +14,7 @@ pub use dbx_core::connection::{
};
use dbx_core::database_capabilities;
use dbx_core::db;
use dbx_core::db::agent_driver::AgentMethod;
use dbx_core::db::agent_driver::{AgentDriverClient, AgentMethod};
use dbx_core::models::connection::{
database_info_from_protocol_value, rewrite_jdbc_url_host, ConnectionConfig, ConnectionTestResult,
DatabaseConnectionInfo, DatabaseType,
@@ -34,6 +34,36 @@ fn mongo_legacy_connect_params(config: &ConnectionConfig, host: &str, port: u16)
})
}
fn mongo_legacy_fallback_error(native_error: &str, stage: &str, fallback_error: &str) -> String {
format!("{native_error}\n\n{stage}: {fallback_error}")
}
async fn spawn_mongo_legacy_fallback_agent(
state: &AppState,
db_type: &DatabaseType,
native_error: &str,
) -> Result<AgentDriverClient, String> {
let agent_key =
dbx_core::agent_manager::AgentManager::db_type_to_agent_key(db_type, Some(MONGO_LEGACY_DRIVER_PROFILE))
.ok_or_else(|| {
mongo_legacy_fallback_error(
native_error,
"Failed to prepare MongoDB (Legacy) fallback driver",
"Agent mapping is unavailable",
)
})?;
dbx_core::agent_service::ensure_agent_driver_ready(&state.agent_manager, agent_key).await.map_err(|error| {
mongo_legacy_fallback_error(native_error, "Failed to prepare MongoDB (Legacy) fallback driver", &error)
})?;
state.agent_manager.spawn(db_type, Some(MONGO_LEGACY_DRIVER_PROFILE)).await.map_err(|error| {
mongo_legacy_fallback_error(
native_error,
"Fallback with MongoDB (Legacy) driver failed",
&mongo_legacy_error_with_auth_hint(&error),
)
})
}
fn mark_mongo_legacy_driver(config: &mut ConnectionConfig) -> bool {
if config.db_type != DatabaseType::MongoDb {
return false;
@@ -169,8 +199,8 @@ mod tests {
use super::load_connection_configs;
use super::{
connect_sqlite_from_config, gaussdb_m_jdbc_command_config, mark_mongo_legacy_driver,
mongo_legacy_connect_params, persist_mongo_legacy_driver_profile, save_connection_configs,
sync_connection_configs, MONGO_LEGACY_DRIVER_LABEL, MONGO_LEGACY_DRIVER_PROFILE,
mongo_legacy_connect_params, mongo_legacy_fallback_error, persist_mongo_legacy_driver_profile,
save_connection_configs, sync_connection_configs, MONGO_LEGACY_DRIVER_LABEL, MONGO_LEGACY_DRIVER_PROFILE,
};
use dbx_core::connection::{AppState, PoolKind};
use dbx_core::models::connection::{AttachedDatabaseConfig, ConnectionConfig, DatabaseType};
@@ -410,6 +440,30 @@ mod tests {
assert!(!mark_mongo_legacy_driver(&mut config));
}
#[test]
fn automatic_mongo_desktop_paths_share_the_ensure_helper() {
let source = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/commands/connection.rs"));
let helper_call = ["spawn_mongo_legacy_fallback_", "agent("].concat();
let ensure_call = ["ensure_agent_driver_", "ready("].concat();
assert_eq!(source.matches(&helper_call).count(), 3);
assert_eq!(source.matches(&ensure_call).count(), 1);
}
#[test]
fn mongo_legacy_fallback_error_preserves_native_and_agent_errors() {
let error = mongo_legacy_fallback_error(
"native wire version error",
"Failed to prepare MongoDB (Legacy) fallback driver",
"registry unavailable",
);
assert_eq!(
error,
"native wire version error\n\nFailed to prepare MongoDB (Legacy) fallback driver: registry unavailable"
);
}
#[tokio::test]
async fn persist_mongo_legacy_driver_profile_updates_only_the_target_connection() {
let dir = std::env::temp_dir().join(format!("dbx-tauri-mongo-profile-{}", uuid::Uuid::new_v4()));
@@ -975,12 +1029,13 @@ async fn test_connection_with_info_inner(
Err(e) => e,
};
if should_retry_mongo_with_legacy_driver(&native_err) {
let am = &state.agent_manager;
let mut client = am.spawn(&config.db_type, Some("mongodb-legacy")).await?;
let mut client =
spawn_mongo_legacy_fallback_agent(state.as_ref(), &config.db_type, &native_err).await?;
client.connect(mongo_legacy_connect_params(&config, &host, port)).await.map_err(|err| {
format!(
"{native_err}\n\nFallback with MongoDB (Legacy) driver failed: {}",
mongo_legacy_error_with_auth_hint(&err)
mongo_legacy_fallback_error(
&native_err,
"Fallback with MongoDB (Legacy) driver failed",
&mongo_legacy_error_with_auth_hint(&err),
)
})?;
client.disconnect().await.ok();
@@ -1380,12 +1435,14 @@ pub async fn connect_db(
if should_retry_mongo_with_legacy_driver(&native_err) {
log::info!("Native MongoDB driver failed ({native_err}), falling back to agent driver");
let mut client =
state.agent_manager.spawn(&db_config.db_type, Some(MONGO_LEGACY_DRIVER_PROFILE)).await?;
spawn_mongo_legacy_fallback_agent(state.inner().as_ref(), &db_config.db_type, &native_err)
.await?;
state.ensure_current_connection_attempt(&id, Some(attempt)).await?;
client.connect(mongo_legacy_connect_params(&db_config, &host, port)).await.map_err(|err| {
format!(
"{native_err}\n\nFallback with MongoDB (Legacy) driver failed: {}",
mongo_legacy_error_with_auth_hint(&err)
mongo_legacy_fallback_error(
&native_err,
"Fallback with MongoDB (Legacy) driver failed",
&mongo_legacy_error_with_auth_hint(&err),
)
})?;
state.ensure_current_connection_attempt(&id, Some(attempt)).await?;