diff --git a/lib/src/api/engine/any/native.rs b/lib/src/api/engine/any/native.rs index 83bb4e96..f31d41f1 100644 --- a/lib/src/api/engine/any/native.rs +++ b/lib/src/api/engine/any/native.rs @@ -20,6 +20,7 @@ use crate::api::ExtraFeatures; use crate::api::Response; use crate::api::Result; use crate::api::Surreal; +use crate::error::Db as DbError; use flume::Receiver; use once_cell::sync::OnceCell; #[cfg(feature = "protocol-http")] @@ -62,99 +63,137 @@ impl Connection for Any { let mut features = HashSet::new(); match address.endpoint.scheme() { - #[cfg(feature = "kv-fdb")] "fdb" => { - features.insert(ExtraFeatures::Backup); - engine::local::native::router(address, conn_tx, route_rx); - conn_rx.into_recv_async().await?? - } - - #[cfg(feature = "kv-mem")] - "mem" => { - features.insert(ExtraFeatures::Backup); - engine::local::native::router(address, conn_tx, route_rx); - conn_rx.into_recv_async().await?? - } - - #[cfg(feature = "kv-rocksdb")] - "rocksdb" => { - features.insert(ExtraFeatures::Backup); - engine::local::native::router(address, conn_tx, route_rx); - conn_rx.into_recv_async().await?? - } - - #[cfg(feature = "kv-rocksdb")] - "file" => { - features.insert(ExtraFeatures::Backup); - engine::local::native::router(address, conn_tx, route_rx); - conn_rx.into_recv_async().await?? - } - - #[cfg(feature = "kv-tikv")] - "tikv" => { - features.insert(ExtraFeatures::Backup); - engine::local::native::router(address, conn_tx, route_rx); - conn_rx.into_recv_async().await?? - } - - #[cfg(feature = "protocol-http")] - "http" | "https" => { - features.insert(ExtraFeatures::Auth); - features.insert(ExtraFeatures::Backup); - let headers = http::default_headers(); - #[allow(unused_mut)] - let mut builder = ClientBuilder::new().default_headers(headers); - #[cfg(any(feature = "native-tls", feature = "rustls"))] - if let Some(tls) = address.tls_config { - builder = match tls { - #[cfg(feature = "native-tls")] - Tls::Native(config) => builder.use_preconfigured_tls(config), - #[cfg(feature = "rustls")] - Tls::Rust(config) => builder.use_preconfigured_tls(config), - }; + #[cfg(feature = "kv-fdb")] + { + features.insert(ExtraFeatures::Backup); + engine::local::native::router(address, conn_tx, route_rx); + conn_rx.into_recv_async().await?? } - let client = builder.build()?; - let base_url = address.endpoint; - engine::remote::http::health( - client.get(base_url.join(Method::Health.as_str())?), - ) - .await?; - engine::remote::http::native::router(base_url, client, route_rx); + + #[cfg(not(feature = "kv-fdb"))] + return Err( + DbError::Ds("Cannot connect to the `foundationdb` storage engine as it is not enabled in this build of SurrealDB".to_owned()).into() + ); } - #[cfg(feature = "protocol-ws")] - "ws" | "wss" => { - features.insert(ExtraFeatures::Auth); - let url = address.endpoint.join(engine::remote::ws::PATH)?; - #[cfg(any(feature = "native-tls", feature = "rustls"))] - let maybe_connector = address.tls_config.map(Connector::from); - #[cfg(not(any(feature = "native-tls", feature = "rustls")))] - let maybe_connector = None; - let config = WebSocketConfig { - max_send_queue: match capacity { - 0 => None, - capacity => Some(capacity), - }, - max_message_size: Some(engine::remote::ws::native::MAX_MESSAGE_SIZE), - max_frame_size: Some(engine::remote::ws::native::MAX_FRAME_SIZE), - accept_unmasked_frames: false, - }; - let socket = engine::remote::ws::native::connect( - &url, - Some(config), - maybe_connector.clone(), - ) - .await?; - engine::remote::ws::native::router( - url, - maybe_connector, - capacity, - config, - socket, - route_rx, + "mem" => { + #[cfg(feature = "kv-mem")] + { + features.insert(ExtraFeatures::Backup); + engine::local::native::router(address, conn_tx, route_rx); + conn_rx.into_recv_async().await?? + } + + #[cfg(not(feature = "kv-mem"))] + return Err( + DbError::Ds("Cannot connect to the `memory` storage engine as it is not enabled in this build of SurrealDB".to_owned()).into() ); } + "file" | "rocksdb" => { + #[cfg(feature = "kv-rocksdb")] + { + features.insert(ExtraFeatures::Backup); + engine::local::native::router(address, conn_tx, route_rx); + conn_rx.into_recv_async().await?? + } + + #[cfg(not(feature = "kv-rocksdb"))] + return Err(DbError::Ds( + "Cannot connect to the `rocksdb` storage engine as it is not enabled in this build of SurrealDB".to_owned(), + ) + .into()); + } + + "tikv" => { + #[cfg(feature = "kv-tikv")] + { + features.insert(ExtraFeatures::Backup); + engine::local::native::router(address, conn_tx, route_rx); + conn_rx.into_recv_async().await?? + } + + #[cfg(not(feature = "kv-tikv"))] + return Err( + DbError::Ds("Cannot connect to the `tikv` storage engine as it is not enabled in this build of SurrealDB".to_owned()).into() + ); + } + + "http" | "https" => { + #[cfg(feature = "protocol-http")] + { + features.insert(ExtraFeatures::Auth); + features.insert(ExtraFeatures::Backup); + let headers = http::default_headers(); + #[allow(unused_mut)] + let mut builder = ClientBuilder::new().default_headers(headers); + #[cfg(any(feature = "native-tls", feature = "rustls"))] + if let Some(tls) = address.tls_config { + builder = match tls { + #[cfg(feature = "native-tls")] + Tls::Native(config) => builder.use_preconfigured_tls(config), + #[cfg(feature = "rustls")] + Tls::Rust(config) => builder.use_preconfigured_tls(config), + }; + } + let client = builder.build()?; + let base_url = address.endpoint; + engine::remote::http::health( + client.get(base_url.join(Method::Health.as_str())?), + ) + .await?; + engine::remote::http::native::router(base_url, client, route_rx); + } + + #[cfg(not(feature = "protocol-http"))] + return Err(DbError::Ds( + "Cannot connect to the `HTTP` remote engine as it is not enabled in this build of SurrealDB".to_owned(), + ) + .into()); + } + + "ws" | "wss" => { + #[cfg(feature = "protocol-ws")] + { + features.insert(ExtraFeatures::Auth); + let url = address.endpoint.join(engine::remote::ws::PATH)?; + #[cfg(any(feature = "native-tls", feature = "rustls"))] + let maybe_connector = address.tls_config.map(Connector::from); + #[cfg(not(any(feature = "native-tls", feature = "rustls")))] + let maybe_connector = None; + let config = WebSocketConfig { + max_send_queue: match capacity { + 0 => None, + capacity => Some(capacity), + }, + max_message_size: Some(engine::remote::ws::native::MAX_MESSAGE_SIZE), + max_frame_size: Some(engine::remote::ws::native::MAX_FRAME_SIZE), + accept_unmasked_frames: false, + }; + let socket = engine::remote::ws::native::connect( + &url, + Some(config), + maybe_connector.clone(), + ) + .await?; + engine::remote::ws::native::router( + url, + maybe_connector, + capacity, + config, + socket, + route_rx, + ); + } + + #[cfg(not(feature = "protocol-ws"))] + return Err(DbError::Ds( + "Cannot connect to the `WebSocket` remote engine as it is not enabled in this build of SurrealDB".to_owned(), + ) + .into()); + } + scheme => { return Err(Error::Scheme(scheme.to_owned()).into()); } diff --git a/lib/src/api/engine/any/wasm.rs b/lib/src/api/engine/any/wasm.rs index a394fa9f..6d9ca69b 100644 --- a/lib/src/api/engine/any/wasm.rs +++ b/lib/src/api/engine/any/wasm.rs @@ -15,6 +15,7 @@ use crate::api::ExtraFeatures; use crate::api::Response; use crate::api::Result; use crate::api::Surreal; +use crate::error::Db as DbError; use flume::Receiver; use once_cell::sync::OnceCell; use serde::de::DeserializeOwned; @@ -50,69 +51,113 @@ impl Connection for Any { let mut features = HashSet::new(); match address.endpoint.scheme() { - #[cfg(feature = "kv-fdb")] "fdb" => { - engine::local::wasm::router(address, conn_tx, route_rx); - if let Err(error) = conn_rx.into_recv_async().await? { - return Err(error); + #[cfg(feature = "kv-fdb")] + { + engine::local::wasm::router(address, conn_tx, route_rx); + if let Err(error) = conn_rx.into_recv_async().await? { + return Err(error); + } } + + #[cfg(not(feature = "kv-fdb"))] + return Err( + DbError::Ds("Cannot connect to the `foundationdb` storage engine as it is not enabled in this build of SurrealDB".to_owned()).into() + ); } - #[cfg(feature = "kv-indxdb")] "indxdb" => { - engine::local::wasm::router(address, conn_tx, route_rx); - if let Err(error) = conn_rx.into_recv_async().await? { - return Err(error); + #[cfg(feature = "kv-indxdb")] + { + engine::local::wasm::router(address, conn_tx, route_rx); + if let Err(error) = conn_rx.into_recv_async().await? { + return Err(error); + } } + + #[cfg(not(feature = "kv-indxdb"))] + return Err( + DbError::Ds("Cannot connect to the `indxdb` storage engine as it is not enabled in this build of SurrealDB".to_owned()).into() + ); } - #[cfg(feature = "kv-mem")] "mem" => { - engine::local::wasm::router(address, conn_tx, route_rx); - if let Err(error) = conn_rx.into_recv_async().await? { - return Err(error); + #[cfg(feature = "kv-mem")] + { + engine::local::wasm::router(address, conn_tx, route_rx); + if let Err(error) = conn_rx.into_recv_async().await? { + return Err(error); + } } + + #[cfg(not(feature = "kv-mem"))] + return Err( + DbError::Ds("Cannot connect to the `memory` storage engine as it is not enabled in this build of SurrealDB".to_owned()).into() + ); } - #[cfg(feature = "kv-rocksdb")] - "rocksdb" => { - engine::local::wasm::router(address, conn_tx, route_rx); - if let Err(error) = conn_rx.into_recv_async().await? { - return Err(error); + "file" | "rocksdb" => { + #[cfg(feature = "kv-rocksdb")] + { + engine::local::wasm::router(address, conn_tx, route_rx); + if let Err(error) = conn_rx.into_recv_async().await? { + return Err(error); + } } + + #[cfg(not(feature = "kv-rocksdb"))] + return Err(DbError::Ds( + "Cannot connect to the `rocksdb` storage engine as it is not enabled in this build of SurrealDB".to_owned(), + ) + .into()); } - #[cfg(feature = "kv-rocksdb")] - "file" => { - engine::local::wasm::router(address, conn_tx, route_rx); - if let Err(error) = conn_rx.into_recv_async().await? { - return Err(error); - } - } - - #[cfg(feature = "kv-tikv")] "tikv" => { - engine::local::wasm::router(address, conn_tx, route_rx); - if let Err(error) = conn_rx.into_recv_async().await? { - return Err(error); + #[cfg(feature = "kv-tikv")] + { + engine::local::wasm::router(address, conn_tx, route_rx); + if let Err(error) = conn_rx.into_recv_async().await? { + return Err(error); + } } + + #[cfg(not(feature = "kv-tikv"))] + return Err( + DbError::Ds("Cannot connect to the `tikv` storage engine as it is not enabled in this build of SurrealDB".to_owned()).into() + ); } - #[cfg(feature = "protocol-http")] "http" | "https" => { - features.insert(ExtraFeatures::Auth); - engine::remote::http::wasm::router(address, conn_tx, route_rx); + #[cfg(feature = "protocol-http")] + { + features.insert(ExtraFeatures::Auth); + engine::remote::http::wasm::router(address, conn_tx, route_rx); + } + + #[cfg(not(feature = "protocol-http"))] + return Err(DbError::Ds( + "Cannot connect to the `HTTP` remote engine as it is not enabled in this build of SurrealDB".to_owned(), + ) + .into()); } - #[cfg(feature = "protocol-ws")] "ws" | "wss" => { - features.insert(ExtraFeatures::Auth); - let mut address = address; - address.endpoint = address.endpoint.join(engine::remote::ws::PATH)?; - engine::remote::ws::wasm::router(address, capacity, conn_tx, route_rx); - if let Err(error) = conn_rx.into_recv_async().await? { - return Err(error); + #[cfg(feature = "protocol-ws")] + { + features.insert(ExtraFeatures::Auth); + let mut address = address; + address.endpoint = address.endpoint.join(engine::remote::ws::PATH)?; + engine::remote::ws::wasm::router(address, capacity, conn_tx, route_rx); + if let Err(error) = conn_rx.into_recv_async().await? { + return Err(error); + } } + + #[cfg(not(feature = "protocol-ws"))] + return Err(DbError::Ds( + "Cannot connect to the `WebSocket` remote engine as it is not enabled in this build of SurrealDB".to_owned(), + ) + .into()); } scheme => { diff --git a/lib/src/api/err/mod.rs b/lib/src/api/err/mod.rs index 2bfded86..8101d781 100644 --- a/lib/src/api/err/mod.rs +++ b/lib/src/api/err/mod.rs @@ -24,7 +24,7 @@ pub enum Error { #[error("There was an error processing a remote WS request")] Ws(String), - /// There specified scheme does not match any supported protocol or storage engine + /// The specified scheme does not match any supported protocol or storage engine #[error("Unsupported protocol or storage engine, `{0}`")] Scheme(String), diff --git a/lib/src/kvs/ds.rs b/lib/src/kvs/ds.rs index 7cd9f39e..f3c81766 100644 --- a/lib/src/kvs/ds.rs +++ b/lib/src/kvs/ds.rs @@ -97,74 +97,104 @@ impl Datastore { /// ``` pub async fn new(path: &str) -> Result { match path { - #[cfg(feature = "kv-mem")] "memory" => { - info!(target: LOG, "Starting kvs store in {}", path); - let v = super::mem::Datastore::new().await.map(|v| Datastore { - inner: Inner::Mem(v), - }); - info!(target: LOG, "Started kvs store in {}", path); - v + #[cfg(feature = "kv-mem")] + { + info!(target: LOG, "Starting kvs store in {}", path); + let v = super::mem::Datastore::new().await.map(|v| Datastore { + inner: Inner::Mem(v), + }); + info!(target: LOG, "Started kvs store in {}", path); + v + } + + #[cfg(not(feature = "kv-mem"))] + return Err(Error::Ds("Cannot connect to the `memory` storage engine as it is not enabled in this build of SurrealDB".to_owned())); } // Parse and initiate an File database - #[cfg(feature = "kv-rocksdb")] s if s.starts_with("file:") => { - info!(target: LOG, "Starting kvs store at {}", path); - let s = s.trim_start_matches("file://"); - let s = s.trim_start_matches("file:"); - let v = super::rocksdb::Datastore::new(s).await.map(|v| Datastore { - inner: Inner::RocksDB(v), - }); - info!(target: LOG, "Started kvs store at {}", path); - v + #[cfg(feature = "kv-rocksdb")] + { + info!(target: LOG, "Starting kvs store at {}", path); + let s = s.trim_start_matches("file://"); + let s = s.trim_start_matches("file:"); + let v = super::rocksdb::Datastore::new(s).await.map(|v| Datastore { + inner: Inner::RocksDB(v), + }); + info!(target: LOG, "Started kvs store at {}", path); + v + } + + #[cfg(not(feature = "kv-rocksdb"))] + return Err(Error::Ds("Cannot connect to the `rocksdb` storage engine as it is not enabled in this build of SurrealDB".to_owned())); } // Parse and initiate an RocksDB database - #[cfg(feature = "kv-rocksdb")] s if s.starts_with("rocksdb:") => { - info!(target: LOG, "Starting kvs store at {}", path); - let s = s.trim_start_matches("rocksdb://"); - let s = s.trim_start_matches("rocksdb:"); - let v = super::rocksdb::Datastore::new(s).await.map(|v| Datastore { - inner: Inner::RocksDB(v), - }); - info!(target: LOG, "Started kvs store at {}", path); - v + #[cfg(feature = "kv-rocksdb")] + { + info!(target: LOG, "Starting kvs store at {}", path); + let s = s.trim_start_matches("rocksdb://"); + let s = s.trim_start_matches("rocksdb:"); + let v = super::rocksdb::Datastore::new(s).await.map(|v| Datastore { + inner: Inner::RocksDB(v), + }); + info!(target: LOG, "Started kvs store at {}", path); + v + } + + #[cfg(not(feature = "kv-rocksdb"))] + return Err(Error::Ds("Cannot connect to the `rocksdb` storage engine as it is not enabled in this build of SurrealDB".to_owned())); } // Parse and initiate an IndxDB database - #[cfg(feature = "kv-indxdb")] s if s.starts_with("indxdb:") => { - info!(target: LOG, "Starting kvs store at {}", path); - let s = s.trim_start_matches("indxdb://"); - let s = s.trim_start_matches("indxdb:"); - let v = super::indxdb::Datastore::new(s).await.map(|v| Datastore { - inner: Inner::IndxDB(v), - }); - info!(target: LOG, "Started kvs store at {}", path); - v + #[cfg(feature = "kv-indxdb")] + { + info!(target: LOG, "Starting kvs store at {}", path); + let s = s.trim_start_matches("indxdb://"); + let s = s.trim_start_matches("indxdb:"); + let v = super::indxdb::Datastore::new(s).await.map(|v| Datastore { + inner: Inner::IndxDB(v), + }); + info!(target: LOG, "Started kvs store at {}", path); + v + } + + #[cfg(not(feature = "kv-indxdb"))] + return Err(Error::Ds("Cannot connect to the `indxdb` storage engine as it is not enabled in this build of SurrealDB".to_owned())); } // Parse and initiate a TiKV database - #[cfg(feature = "kv-tikv")] s if s.starts_with("tikv:") => { - info!(target: LOG, "Connecting to kvs store at {}", path); - let s = s.trim_start_matches("tikv://"); - let s = s.trim_start_matches("tikv:"); - let v = super::tikv::Datastore::new(s).await.map(|v| Datastore { - inner: Inner::TiKV(v), - }); - info!(target: LOG, "Connected to kvs store at {}", path); - v + #[cfg(feature = "kv-tikv")] + { + info!(target: LOG, "Connecting to kvs store at {}", path); + let s = s.trim_start_matches("tikv://"); + let s = s.trim_start_matches("tikv:"); + let v = super::tikv::Datastore::new(s).await.map(|v| Datastore { + inner: Inner::TiKV(v), + }); + info!(target: LOG, "Connected to kvs store at {}", path); + v + } + + #[cfg(not(feature = "kv-tikv"))] + return Err(Error::Ds("Cannot connect to the `tikv` storage engine as it is not enabled in this build of SurrealDB".to_owned())); } // Parse and initiate a FoundationDB database - #[cfg(feature = "kv-fdb")] s if s.starts_with("fdb:") => { - info!(target: LOG, "Connecting to kvs store at {}", path); - let s = s.trim_start_matches("fdb://"); - let s = s.trim_start_matches("fdb:"); - let v = super::fdb::Datastore::new(s).await.map(|v| Datastore { - inner: Inner::FDB(v), - }); - info!(target: LOG, "Connected to kvs store at {}", path); - v + #[cfg(feature = "kv-fdb")] + { + info!(target: LOG, "Connecting to kvs store at {}", path); + let s = s.trim_start_matches("fdb://"); + let s = s.trim_start_matches("fdb:"); + let v = super::fdb::Datastore::new(s).await.map(|v| Datastore { + inner: Inner::FDB(v), + }); + info!(target: LOG, "Connected to kvs store at {}", path); + v + } + + #[cfg(not(feature = "kv-fdb"))] + return Err(Error::Ds("Cannot connect to the `foundationdb` storage engine as it is not enabled in this build of SurrealDB".to_owned())); } // The datastore path is not valid _ => {