typedb_driver/database/
database_manager.rs1use std::{io::BufReader, path::Path, sync::Arc};
21
22use itertools::Itertools;
23use typedb_protocol::migration::Item;
24
25use super::Database;
26use crate::{
27 common::Result,
28 connection::server::{server_manager::ServerManager, server_routing::ServerRouting},
29 database::migration::{ProtoMessageIterator, try_open_import_file},
30 info::DatabaseInfo,
31 resolve,
32};
33
34#[derive(Debug)]
36pub struct DatabaseManager {
37 server_manager: Arc<ServerManager>,
38}
39
40impl DatabaseManager {
42 pub(crate) fn new(server_manager: Arc<ServerManager>) -> Result<Self> {
43 Ok(Self { server_manager })
44 }
45
46 #[cfg_attr(feature = "sync", doc = "driver.databases().all();")]
52 #[cfg_attr(not(feature = "sync"), doc = "driver.databases().all().await;")]
53 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
55 pub async fn all(&self) -> Result<Vec<Arc<Database>>> {
56 self.server_manager
57 .execute(ServerRouting::Auto, move |server_connection| async move {
58 server_connection
59 .all_databases()
60 .await?
61 .into_iter()
62 .map(|database_info| self.try_build_database(database_info))
63 .try_collect()
64 })
65 .await
66 }
67
68 #[cfg_attr(feature = "sync", doc = "driver.databases().get(name);")]
78 #[cfg_attr(not(feature = "sync"), doc = "driver.databases().get(name).await;")]
79 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
81 pub async fn get(&self, name: impl Into<String>) -> Result<Arc<Database>> {
82 let name = name.into();
83 let database_info = self
84 .server_manager
85 .execute(ServerRouting::Auto, move |server_connection| {
86 let name = name.clone();
87 async move { server_connection.get_database(name).await }
88 })
89 .await?;
90 self.try_build_database(database_info)
91 }
92
93 #[cfg_attr(feature = "sync", doc = "driver.databases().contains(name);")]
103 #[cfg_attr(not(feature = "sync"), doc = "driver.databases().contains(name).await;")]
104 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
106 pub async fn contains(&self, name: impl Into<String>) -> Result<bool> {
107 let name = name.into();
108 self.server_manager
109 .execute(ServerRouting::Auto, move |server_connection| {
110 let name = name.clone();
111 async move { server_connection.contains_database(name).await }
112 })
113 .await
114 }
115
116 #[cfg_attr(feature = "sync", doc = "driver.databases().create(name);")]
126 #[cfg_attr(not(feature = "sync"), doc = "driver.databases().create(name).await;")]
127 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
129 pub async fn create(&self, name: impl Into<String>) -> Result {
130 let name = name.into();
131 self.server_manager
132 .execute(ServerRouting::Auto, move |server_connection| {
133 let name = name.clone();
134 async move { server_connection.create_database(name).await }
135 })
136 .await
137 }
138
139 #[cfg_attr(feature = "sync", doc = "driver.databases().import_from_file(name, schema, data_path);")]
154 #[cfg_attr(not(feature = "sync"), doc = "driver.databases().import_from_file(name, schema, data_path).await;")]
155 #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
157 pub async fn import_from_file(
158 &self,
159 name: impl Into<String>,
160 schema: impl Into<String>,
161 data_file_path: impl AsRef<Path>,
162 ) -> Result {
163 const ITEM_BATCH_SIZE: usize = 250;
164
165 let name = name.into();
166 let schema: String = schema.into();
167 let schema_ref: &str = schema.as_ref();
168 let data_file_path = data_file_path.as_ref();
169
170 self.server_manager
171 .execute(ServerRouting::Auto, move |server_connection| {
172 let name = name.clone();
173 async move {
174 let file = try_open_import_file(data_file_path)?;
175 let mut import_stream = server_connection.import_database(name, schema_ref.to_string()).await?;
176
177 let mut item_buffer = Vec::with_capacity(ITEM_BATCH_SIZE);
178 let mut read_item_iterator = ProtoMessageIterator::<Item, _>::new(BufReader::new(file));
179
180 while let Some(item) = read_item_iterator.next() {
181 let item = item?;
182 item_buffer.push(item);
183 if item_buffer.len() >= ITEM_BATCH_SIZE {
184 import_stream.send_items(item_buffer.split_off(0))?;
185 }
186 }
187
188 if !item_buffer.is_empty() {
189 import_stream.send_items(item_buffer)?;
190 }
191
192 resolve!(import_stream.done())
193 }
194 })
195 .await
196 }
197
198 fn try_build_database(&self, database_info: DatabaseInfo) -> Result<Arc<Database>> {
199 Database::new(database_info, self.server_manager.clone()).map(Arc::new)
200 }
201}