1use std::{collections::HashSet, fmt, sync::Arc};
20
21use tracing::{debug, error};
22
23use crate::{
24 Credentials, DatabaseManager, DriverOptions, Transaction, TransactionOptions, TransactionType, UserManager,
25 common::{Addresses, Result},
26 connection::{
27 runtime::BackgroundRuntime,
28 server::{
29 AvailableServer, Server, server_connection::ServerConnection, server_manager::ServerManager,
30 server_routing::ServerRouting, server_version::ServerVersion,
31 },
32 },
33};
34
35pub struct TypeDBDriver {
37 server_manager: Arc<ServerManager>,
38 database_manager: DatabaseManager,
39 user_manager: UserManager,
40 background_runtime: Arc<BackgroundRuntime>,
41}
42
43impl TypeDBDriver {
44 const DRIVER_LANG: &'static str = "rust";
45 const VERSION: &'static str = match option_env!("CARGO_PKG_VERSION") {
46 None => "0.0.0",
47 Some(version) => version,
48 };
49
50 pub const DEFAULT_ADDRESS: &'static str = "127.0.0.1:1729";
51
52 #[cfg_attr(
64 feature = "sync",
65 doc = "TypeDBDriver::new(Addresses::try_from_address_str(\"127.0.0.1:1729\").unwrap(), Credentials::new(\"username\", \"password\"), DriverOptions::new(true, None))"
66 )]
67 #[cfg_attr(
68 not(feature = "sync"),
69 doc = "TypeDBDriver::new(Addresses::try_from_address_str(\"127.0.0.1:1729\").unwrap(), Credentials::new(\"username\", \"password\"), DriverOptions::new(true, None)).await"
70 )]
71 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
73 pub async fn new(addresses: Addresses, credentials: Credentials, driver_options: DriverOptions) -> Result<Self> {
74 debug!("Creating new TypeDB driver connection to {:?}", addresses);
75 Self::new_with_description(addresses, credentials, driver_options, Self::DRIVER_LANG).await
76 }
77
78 #[cfg_attr(
93 feature = "sync",
94 doc = "TypeDBDriver::new_with_description(Addresses::try_from_address_str(\"127.0.0.1:1729\").unwrap(), Credentials::new(\"username\", \"password\"), DriverOptions::new(true, None), \"rust\")"
95 )]
96 #[cfg_attr(
97 not(feature = "sync"),
98 doc = "TypeDBDriver::new_with_description(Addresses::try_from_address_str(\"127.0.0.1:1729\").unwrap(), Credentials::new(\"username\", \"password\"), DriverOptions::new(true, None), \"rust\").await"
99 )]
100 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
102 pub async fn new_with_description(
103 addresses: Addresses,
104 credentials: Credentials,
105 driver_options: DriverOptions,
106 driver_lang: impl AsRef<str>,
107 ) -> Result<Self> {
108 debug!("Initializing TypeDB driver with description: {}", driver_lang.as_ref());
109 let background_runtime = Arc::new(BackgroundRuntime::new()?);
110
111 debug!("Establishing server connection to {:?}", addresses);
112 let server_manager = Arc::new(
113 ServerManager::new(
114 background_runtime.clone(),
115 addresses,
116 credentials,
117 driver_options,
118 driver_lang.as_ref(),
119 Self::VERSION,
120 )
121 .await?,
122 );
123 debug!("Successfully connected to servers");
124
125 let database_manager = DatabaseManager::new(server_manager.clone())?;
126 let user_manager = UserManager::new(server_manager.clone());
127 debug!("Created database manager and user manager");
128
129 debug!("TypeDB driver initialization completed successfully");
130 Ok(Self { server_manager, database_manager, user_manager, background_runtime })
131 }
132
133 pub fn is_open(&self) -> bool {
141 self.background_runtime.is_open()
142 }
143
144 pub fn databases(&self) -> &DatabaseManager {
152 &self.database_manager
153 }
154
155 pub fn users(&self) -> &UserManager {
163 &self.user_manager
164 }
165
166 #[cfg_attr(feature = "sync", doc = "driver.server_version()")]
174 #[cfg_attr(not(feature = "sync"), doc = "driver.server_version().await")]
175 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
177 pub async fn server_version(&self) -> Result<ServerVersion> {
178 self.server_version_with_routing(ServerRouting::Auto).await
179 }
180
181 #[cfg_attr(feature = "sync", doc = "driver.server_version_with_routing(ServerRouting::Auto);")]
191 #[cfg_attr(not(feature = "sync"), doc = "driver.server_version_with_routing(ServerRouting::Auto).await;")]
192 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
194 pub async fn server_version_with_routing(&self, server_routing: ServerRouting) -> Result<ServerVersion> {
195 self.server_manager
196 .execute(server_routing, |server_connection| async move { server_connection.version().await })
197 .await
198 }
199
200 #[cfg_attr(feature = "sync", doc = "driver.servers();")]
208 #[cfg_attr(not(feature = "sync"), doc = "driver.servers().await;")]
209 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
211 pub async fn servers(&self) -> Result<HashSet<Server>> {
212 self.servers_with_routing(ServerRouting::Auto).await
213 }
214
215 #[cfg_attr(feature = "sync", doc = "driver.servers_with_routing(ServerRouting::Auto);")]
225 #[cfg_attr(not(feature = "sync"), doc = "driver.servers_with_routing(ServerRouting::Auto).await;")]
226 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
228 pub async fn servers_with_routing(&self, server_routing: ServerRouting) -> Result<HashSet<Server>> {
229 self.server_manager.fetch_servers(server_routing).await
230 }
231
232 #[cfg_attr(feature = "sync", doc = "driver.primary_server();")]
242 #[cfg_attr(not(feature = "sync"), doc = "driver.primary_server().await;")]
243 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
245 pub async fn primary_server(&self) -> Result<Option<AvailableServer>> {
246 self.primary_server_with_routing(ServerRouting::Auto).await
247 }
248
249 #[cfg_attr(feature = "sync", doc = "driver.primary_server_with_routing(ServerRouting::Auto);")]
259 #[cfg_attr(not(feature = "sync"), doc = "driver.primary_server_with_routing(ServerRouting::Auto).await;")]
260 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
262 pub async fn primary_server_with_routing(&self, server_routing: ServerRouting) -> Result<Option<AvailableServer>> {
263 self.server_manager.fetch_primary_server(server_routing).await
264 }
265
266 pub fn options(&self) -> &DriverOptions {
279 self.server_manager.driver_options()
280 }
281
282 pub fn configured_addresses(&self) -> &Addresses {
290 self.server_manager.configured_addresses()
291 }
292
293 #[cfg_attr(feature = "sync", doc = "driver.transaction(database_name, TransactionType::Read);")]
301 #[cfg_attr(not(feature = "sync"), doc = "driver.transaction(database_name, TransactionType::Read).await;")]
302 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
304 pub async fn transaction(
305 &self,
306 database_name: impl AsRef<str>,
307 transaction_type: TransactionType,
308 ) -> Result<Transaction> {
309 self.transaction_with_options(database_name, transaction_type, TransactionOptions::new()).await
310 }
311
312 #[cfg_attr(
324 feature = "sync",
325 doc = "transaction.transaction_with_options(database_name, transaction_type, options)"
326 )]
327 #[cfg_attr(
328 not(feature = "sync"),
329 doc = "transaction.transaction_with_options(database_name, transaction_type, options).await"
330 )]
331 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
333 pub async fn transaction_with_options(
334 &self,
335 database_name: impl AsRef<str>,
336 transaction_type: TransactionType,
337 options: TransactionOptions,
338 ) -> Result<Transaction> {
339 let database_name = database_name.as_ref();
340 let open_fn = |server_connection: ServerConnection| {
341 let options = options.clone();
342 async move { server_connection.open_transaction(database_name, transaction_type, options).await }
343 };
344
345 debug!("Opening transaction for database: {} with type: {:?}", database_name, transaction_type);
346 let transaction_stream = self.server_manager.execute(ServerRouting::Auto, open_fn).await?;
347
348 debug!("Successfully opened transaction for database: {}", database_name);
349 Ok(Transaction::new(transaction_stream))
350 }
351
352 pub fn force_close(&self) -> Result {
360 if !self.is_open() {
361 return Ok(());
362 }
363
364 debug!("Closing TypeDB driver connection");
365 let close_result = self.server_manager.force_close().and(self.background_runtime.force_close());
366 match &close_result {
367 Ok(_) => debug!("Successfully closed TypeDB driver connection"),
368 Err(e) => error!("Failed to close TypeDB driver connection: {}", e),
369 }
370 close_result
371 }
372}
373
374impl fmt::Debug for TypeDBDriver {
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 f.debug_struct("TypeDBDriver").field("server_manager", &self.server_manager).finish()
377 }
378}