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#[derive(Clone)]
18pub struct Db {
19 pool: deadpool_diesel::Pool<ConnectionManager, deadpool::managed::Object<ConnectionManager>>,
20}
21
22impl Db {
23 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 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 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}