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        let span = tracing::Span::current();
50        conn.interact(move |conn| {
51            let _guard = span.enter();
52            <_ as diesel::Connection>::transaction::<R, E, Q>(conn, query)
53        })
54        .await
55        .map_err(|err| E::from(DatabaseError::interact(&msg.to_string(), &err)))?
56    }
57
58    /// Run the query _without_ a transaction
59    pub async fn query<R, E, Q, M>(&self, msg: M, query: Q) -> std::result::Result<R, E>
60    where
61        Q: Send + FnOnce(&mut SqliteConnection) -> std::result::Result<R, E> + 'static,
62        R: Send + 'static,
63        M: Send + ToString,
64        E: From<DatabaseError>,
65        E: std::error::Error + Send + Sync + 'static,
66    {
67        let conn = self
68            .pool
69            .get()
70            .await
71            .map_err(|e| DatabaseError::ConnectionPoolObtainError(Box::new(e)))?;
72
73        conn.interact(move |conn| {
74            let r = query(conn)?;
75            Ok(r)
76        })
77        .await
78        .map_err(|err| E::from(DatabaseError::interact(&msg.to_string(), &err)))?
79    }
80}