1use deadpool_sync::InteractError;
6
7use super::{Result, RunQueryDsl, SqliteConnection};
8
9#[derive(thiserror::Error, Debug)]
10pub enum ConnectionManagerError {
11 #[error("failed to apply connection parameter")]
12 ConnectionParamSetup(#[source] diesel::result::Error),
13 #[error("SQLite pool interaction failed: {0}")]
14 InteractError(String),
15 #[error("failed to create a new connection")]
16 ConnectionCreate(#[source] deadpool_diesel::Error),
17 #[error("failed to recycle connection")]
18 PoolRecycle(#[source] deadpool::managed::RecycleError<deadpool_diesel::Error>),
19}
20
21impl ConnectionManagerError {
22 pub fn interact(msg: &(impl ToString + ?Sized), e: &InteractError) -> Self {
31 let msg = msg.to_string();
32 Self::InteractError(format!("{msg} failed: {e:?}"))
33 }
34}
35
36pub struct ConnectionManager {
40 pub(crate) manager: deadpool_diesel::sqlite::Manager,
41}
42
43impl ConnectionManager {
44 pub fn new(database_path: &str) -> Self {
45 let manager = deadpool_diesel::sqlite::Manager::new(
46 database_path.to_owned(),
47 deadpool_diesel::sqlite::Runtime::Tokio1,
48 );
49 Self { manager }
50 }
51}
52
53impl deadpool::managed::Manager for ConnectionManager {
54 type Type = deadpool_sync::SyncWrapper<SqliteConnection>;
55 type Error = ConnectionManagerError;
56
57 async fn create(&self) -> Result<Self::Type, Self::Error> {
58 let conn = self.manager.create().await.map_err(ConnectionManagerError::ConnectionCreate)?;
59
60 conn.interact(configure_connection_on_creation)
61 .await
62 .map_err(|e| ConnectionManagerError::interact("Connection setup", &e))??;
63 Ok(conn)
64 }
65
66 async fn recycle(
67 &self,
68 conn: &mut Self::Type,
69 metrics: &deadpool_diesel::Metrics,
70 ) -> deadpool::managed::RecycleResult<Self::Error> {
71 self.manager.recycle(conn, metrics).await.map_err(|err| {
72 deadpool::managed::RecycleError::Backend(ConnectionManagerError::PoolRecycle(err))
73 })?;
74 Ok(())
75 }
76}
77
78pub fn configure_connection_on_creation(
79 conn: &mut SqliteConnection,
80) -> Result<(), ConnectionManagerError> {
81 diesel::sql_query("PRAGMA busy_timeout=3000")
83 .execute(conn)
84 .map_err(ConnectionManagerError::ConnectionParamSetup)?;
85
86 diesel::sql_query("PRAGMA journal_mode=WAL")
90 .execute(conn)
91 .map_err(ConnectionManagerError::ConnectionParamSetup)?;
92
93 diesel::sql_query("PRAGMA foreign_keys=ON")
95 .execute(conn)
96 .map_err(ConnectionManagerError::ConnectionParamSetup)?;
97
98 diesel::sql_query("PRAGMA busy_timeout=5000")
100 .execute(conn)
101 .map_err(ConnectionManagerError::ConnectionParamSetup)?;
102 Ok(())
103}