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 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 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}