Skip to main content

miden_node_db/
lib.rs

1mod conv;
2mod errors;
3mod manager;
4
5use std::path::Path;
6
7pub use conv::{DatabaseTypeConversionError, SqlTypeConvert};
8use diesel::{RunQueryDsl, SqliteConnection};
9pub use errors::{DatabaseError, SchemaVerificationError};
10pub use manager::{ConnectionManager, ConnectionManagerError, configure_connection_on_creation};
11use tracing::Instrument;
12
13pub type Result<T, E = DatabaseError> = std::result::Result<T, E>;
14
15/// Database handle that provides fundamental operations that various components of Miden Node can
16/// utililze for their storage needs.
17#[derive(Clone)]
18pub struct Db {
19    pool: deadpool_diesel::Pool<ConnectionManager, deadpool::managed::Object<ConnectionManager>>,
20}
21
22impl Db {
23    /// Creates a new database instance with the provided connection pool.
24    pub fn new(database_filepath: &Path) -> Result<Self, DatabaseError> {
25        let manager = ConnectionManager::new(database_filepath.to_str().unwrap());
26        let pool = deadpool_diesel::Pool::builder(manager).max_size(16).build()?;
27        Ok(Self { pool })
28    }
29
30    /// Create and commit a transaction with the queries added in the provided closure
31    pub async fn transact<R, E, Q, M>(&self, msg: M, query: Q) -> std::result::Result<R, E>
32    where
33        Q: Send
34            + for<'a, 't> FnOnce(&'a mut SqliteConnection) -> std::result::Result<R, E>
35            + 'static,
36        R: Send + 'static,
37        M: Send + ToString,
38        E: From<diesel::result::Error>,
39        E: From<DatabaseError>,
40        E: std::error::Error + Send + Sync + 'static,
41    {
42        let conn = self
43            .pool
44            .get()
45            .in_current_span()
46            .await
47            .map_err(|e| DatabaseError::ConnectionPoolObtainError(Box::new(e)))?;
48
49        conn.interact(|conn| <_ as diesel::Connection>::transaction::<R, E, Q>(conn, query))
50            .in_current_span()
51            .await
52            .map_err(|err| E::from(DatabaseError::interact(&msg.to_string(), &err)))?
53    }
54
55    /// Run the query _without_ a transaction
56    pub async fn query<R, E, Q, M>(&self, msg: M, query: Q) -> std::result::Result<R, E>
57    where
58        Q: Send + FnOnce(&mut SqliteConnection) -> std::result::Result<R, E> + 'static,
59        R: Send + 'static,
60        M: Send + ToString,
61        E: From<DatabaseError>,
62        E: std::error::Error + Send + Sync + 'static,
63    {
64        let conn = self
65            .pool
66            .get()
67            .await
68            .map_err(|e| DatabaseError::ConnectionPoolObtainError(Box::new(e)))?;
69
70        conn.interact(move |conn| {
71            let r = query(conn)?;
72            Ok(r)
73        })
74        .await
75        .map_err(|err| E::from(DatabaseError::interact(&msg.to_string(), &err)))?
76    }
77}