1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#![doc = include_str!("../README.md")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(
nonstandard_style,
rust_2018_idioms,
rustdoc::broken_intra_doc_links,
rustdoc::private_intra_doc_links
)]
#![forbid(non_ascii_idents, unsafe_code)]
#![warn(
deprecated_in_future,
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
unreachable_pub,
unused_import_braces,
unused_labels,
unused_lifetimes,
unused_qualifications,
unused_results
)]
mod config;
use std::sync::atomic::{AtomicUsize, Ordering};
use deadpool::{
async_trait,
managed::{self, RecycleError},
};
use deadpool_sync::SyncWrapper;
pub use deadpool::managed::reexports::*;
pub use deadpool_sync::reexports::*;
pub use rusqlite;
deadpool::managed_reexports!(
"rusqlite",
Manager,
deadpool::managed::Object<Manager>,
rusqlite::Error,
ConfigError
);
pub use self::config::{Config, ConfigError};
pub type Connection = Object;
#[derive(Debug)]
pub struct Manager {
config: Config,
recycle_count: AtomicUsize,
runtime: Runtime,
}
impl Manager {
#[must_use]
pub fn from_config(config: &Config, runtime: Runtime) -> Self {
Self {
config: config.clone(),
recycle_count: AtomicUsize::new(0),
runtime,
}
}
}
#[async_trait]
impl managed::Manager for Manager {
type Type = SyncWrapper<rusqlite::Connection>;
type Error = rusqlite::Error;
async fn create(&self) -> Result<Self::Type, Self::Error> {
let path = self.config.path.clone();
SyncWrapper::new(self.runtime, move || rusqlite::Connection::open(path)).await
}
async fn recycle(&self, conn: &mut Self::Type) -> managed::RecycleResult<Self::Error> {
if conn.is_mutex_poisoned() {
return Err(RecycleError::Message(
"Mutex is poisoned. Connection is considered unusable.".into(),
));
}
let recycle_count = self.recycle_count.fetch_add(1, Ordering::Relaxed);
let n: usize = conn
.interact(move |conn| conn.query_row("SELECT $1", [recycle_count], |row| row.get(0)))
.await
.map_err(|e| RecycleError::Message(format!("{}", e)))??;
if n == recycle_count {
Ok(())
} else {
Err(RecycleError::StaticMessage("Recycle count mismatch"))
}
}
}