1use jfs::{self, Store, IN_MEMORY};
33use std::{io, path::Path};
34
35pub struct JfsConnectionManager(Store);
37
38impl JfsConnectionManager {
39 pub fn file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
41 let cfg = jfs::Config {
42 single: true,
43 ..Default::default()
44 };
45 Self::new_with_cfg(path, cfg)
46 }
47 pub fn dir<P: AsRef<Path>>(path: P) -> io::Result<Self> {
49 let cfg = jfs::Config {
50 single: false,
51 ..Default::default()
52 };
53 Self::new_with_cfg(path, cfg)
54 }
55 pub fn memory() -> Self {
57 Self(Store::new(IN_MEMORY).expect("Unable to initialize in-memory store"))
58 }
59
60 pub fn new_with_cfg<P: AsRef<Path>>(path: P, cfg: jfs::Config) -> io::Result<Self> {
62 let store = Store::new_with_cfg(path, cfg)?;
63 Ok(Self(store))
64 }
65}
66
67impl r2d2::ManageConnection for JfsConnectionManager {
68 type Connection = jfs::Store;
69 type Error = io::Error;
70
71 fn connect(&self) -> Result<Store, Self::Error> {
72 Ok(self.0.clone())
73 }
74
75 fn is_valid(&self, _conn: &mut Self::Connection) -> Result<(), Self::Error> {
76 Ok(())
77 }
78
79 fn has_broken(&self, _: &mut Self::Connection) -> bool {
80 false
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use serde::{Deserialize, Serialize};
88 use std::thread;
89 use tempdir::TempDir;
90
91 #[test]
92 fn multi_threading() {
93 #[derive(Serialize, Deserialize)]
94 struct Data {
95 x: i32,
96 }
97 let dir = TempDir::new("r2d2-jfs-test").expect("Could not create temporary directory");
98 let file = dir.path().join("db.json");
99 let manager = JfsConnectionManager::file(file).unwrap();
100 let pool = r2d2::Pool::builder().max_size(5).build(manager).unwrap();
101 let mut threads: Vec<thread::JoinHandle<()>> = vec![];
102 for i in 0..20 {
103 let pool = pool.clone();
104 let x = Data { x: i };
105 threads.push(thread::spawn(move || {
106 let db = pool.get().unwrap();
107 db.save_with_id(&x, &i.to_string()).unwrap();
108 }));
109 }
110 for t in threads {
111 t.join().unwrap();
112 }
113 let db = pool.get().unwrap();
114 let all = db.all::<Data>().unwrap();
115 assert_eq!(all.len(), 20);
116 for (id, data) in all {
117 assert_eq!(data.x.to_string(), id);
118 }
119 }
120}