Skip to main content

klukai_types/sqlite_pool/
config.rs

1use std::{convert::Infallible, path::PathBuf, time::Duration};
2
3use deadpool::managed::{QueueMode, Timeouts};
4use rusqlite::OpenFlags;
5
6use super::{
7    CreatePoolError, Manager, Pool, PoolBuilder, PoolConfig, Runtime, RusqlitePool, SqliteConn,
8    noop_transform,
9};
10
11/// Configuration object.
12#[derive(Clone, Debug, Default)]
13pub struct Config {
14    /// Path to SQLite database file.
15    pub path: PathBuf,
16
17    /// Open flags for SQLite
18    pub open_flags: OpenFlags,
19
20    /// [`Pool`] configuration.
21    pub pool: PoolConfig,
22}
23
24impl Config {
25    /// Create a new [`Config`] with the given `path` of SQLite database file.
26    #[must_use]
27    pub fn new(path: impl Into<PathBuf>) -> Self {
28        Self {
29            path: path.into(),
30            open_flags: OpenFlags::default(),
31            pool: PoolConfig {
32                max_size: 20,
33                timeouts: Timeouts {
34                    wait: Some(Duration::from_secs(30)),
35                    ..Default::default()
36                },
37                queue_mode: QueueMode::default(),
38            },
39        }
40    }
41
42    pub fn read_only(mut self) -> Self {
43        self.open_flags =
44            OpenFlags::empty() | OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_NO_MUTEX;
45        self
46    }
47
48    pub fn max_size(mut self, value: usize) -> Self {
49        self.pool.max_size = value;
50        self
51    }
52
53    pub fn create_pool(&self) -> Result<RusqlitePool, CreatePoolError> {
54        self.builder(noop_transform)
55            .map_err(CreatePoolError::Config)?
56            .build()
57            .map_err(CreatePoolError::Build)
58    }
59
60    pub fn create_pool_transform<T: SqliteConn>(
61        &self,
62        f: impl Fn(rusqlite::Connection) -> Result<T, rusqlite::Error> + Send + Sync + 'static,
63    ) -> Result<Pool<T>, CreatePoolError> {
64        self.builder(f)
65            .map_err(CreatePoolError::Config)?
66            .build()
67            .map_err(CreatePoolError::Build)
68    }
69
70    /// Creates a new [`PoolBuilder`] using this [`Config`].
71    ///
72    /// # Errors
73    ///
74    /// See [`ConfigError`] for details.
75    ///
76    /// [`RedisError`]: redis::RedisError
77    pub fn builder<T: SqliteConn>(
78        &self,
79        f: impl Fn(rusqlite::Connection) -> Result<T, rusqlite::Error> + Send + Sync + 'static,
80    ) -> Result<PoolBuilder<T>, ConfigError> {
81        let manager = Manager::from_config(self, f);
82        Ok(Pool::builder(manager)
83            .config(self.get_pool_config())
84            .runtime(Runtime::Tokio1))
85    }
86
87    /// Returns [`deadpool::managed::PoolConfig`] which can be used to construct
88    /// a [`deadpool::managed::Pool`] instance.
89    #[must_use]
90    pub fn get_pool_config(&self) -> PoolConfig {
91        self.pool
92    }
93}
94
95/// This error is returned if there is something wrong with the SQLite configuration.
96///
97/// This is just a type alias to [`Infallible`] at the moment as there
98/// is no validation happening at the configuration phase.
99pub type ConfigError = Infallible;