Skip to content

Commit

Permalink
fix(driver-adapters): Idempotent activation of driver adapters (#4222)
Browse files Browse the repository at this point in the history
* fix(driver-adapters): stop caching the previous driver adapter in case of same "provider" on the nth libquery constructor invocation

* fix(driver-adapters): clippy

* fix(driver-adapters): replace "HashMap<String, DriverAdapter>\ registry with simpler "Option<DriverAdapter>"

* fix(driver-adapters): clippy

* remove indirection, change naming

---------

Co-authored-by: Miguel Fernandez <[email protected]>
  • Loading branch information
jkomyno and miguelff authored Sep 11, 2023
1 parent e90b936 commit 4991945
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 35 deletions.
37 changes: 11 additions & 26 deletions query-engine/connectors/sql-query-connector/src/database/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,25 @@ use quaint::{
connector::{IsolationLevel, Transaction},
prelude::{Queryable as QuaintQueryable, *},
};
use std::{
collections::{hash_map::Entry, HashMap},
sync::{Arc, Mutex},
};
use std::sync::{Arc, Mutex};

/// Registry is the type for the global registry of driver adapters.
type Registry = HashMap<String, DriverAdapter>;
static ACTIVE_DRIVER_ADAPTER: Lazy<Mutex<Option<DriverAdapter>>> = Lazy::new(|| Mutex::new(None));

/// REGISTRY is the global registry of Driver Adapters.
static REGISTRY: Lazy<Mutex<Registry>> = Lazy::new(|| Mutex::new(HashMap::new()));
fn active_driver_adapter(provider: &str) -> connector::Result<DriverAdapter> {
let lock = ACTIVE_DRIVER_ADAPTER.lock().unwrap();

fn registered_driver_adapter(provider: &str) -> connector::Result<DriverAdapter> {
let lock = REGISTRY.lock().unwrap();
lock.get(provider)
lock.as_ref()
.map(|conn_ref| conn_ref.to_owned())
.ok_or(ConnectorError::from_kind(ErrorKind::UnsupportedConnector(format!(
"A driver adapter for {} was not registered",
provider
))))
.map(|conn_ref| conn_ref.to_owned())
}

pub fn register_driver_adapter(provider: &str, connector: Arc<dyn TransactionCapable>) -> Result<(), String> {
let mut lock = REGISTRY.lock().unwrap();
let entry = lock.entry(provider.to_string());
match entry {
Entry::Occupied(_) => Err(format!(
"A driver adapter for {} was already registered, and cannot be overridden.",
provider
)),
Entry::Vacant(v) => {
v.insert(DriverAdapter { connector });
Ok(())
}
}
pub fn activate_driver_adapter(connector: Arc<dyn TransactionCapable>) {
let mut lock = ACTIVE_DRIVER_ADAPTER.lock().unwrap();

*lock = Some(DriverAdapter { connector });
}

pub struct Js {
Expand All @@ -69,7 +54,7 @@ impl FromSource for Js {
url: &str,
features: psl::PreviewFeatures,
) -> connector_interface::Result<Js> {
let connector = registered_driver_adapter(source.active_provider)?;
let connector = active_driver_adapter(source.active_provider)?;
let connection_info = get_connection_info(url)?;

Ok(Js {
Expand Down
2 changes: 1 addition & 1 deletion query-engine/connectors/sql-query-connector/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use self::{column_metadata::*, context::Context, filter_conversion::*, query_ext
use quaint::prelude::Queryable;

#[cfg(feature = "driver-adapters")]
pub use database::{register_driver_adapter, Js};
pub use database::{activate_driver_adapter, Js};
pub use database::{FromSource, Mssql, Mysql, PostgreSql, Sqlite};
pub use error::SqlError;

Expand Down
13 changes: 5 additions & 8 deletions query-engine/query-engine-node-api/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,12 @@ impl QueryEngine {
#[cfg(feature = "driver-adapters")]
if let Some(driver) = maybe_driver {
let js_queryable = driver_adapters::from_napi(driver);
let provider_name = schema.connector.provider_name();

match sql_connector::register_driver_adapter(provider_name, Arc::new(js_queryable)) {
Ok(_) => {
connector_mode = ConnectorMode::Js;
tracing::info!("Registered driver adapter for {provider_name}.")
}
Err(err) => tracing::error!("Failed to register driver adapter for {provider_name}. {err}"),
}
sql_connector::activate_driver_adapter(Arc::new(js_queryable));
connector_mode = ConnectorMode::Js;

let provider_name = schema.connector.provider_name();
tracing::info!("Registered driver adapter for {provider_name}.");
}
}

Expand Down

0 comments on commit 4991945

Please sign in to comment.