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
pub mod schema;
pub use diesel::prelude::*;
use home::home_dir;
pub use schema::*;
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
use diesel_migrations::embed_migrations;
use lru::LruCache;
use once_cell::sync::Lazy;
use regex::Regex;
use std::{
error::Error,
sync::{Arc, Mutex},
};
use thread_local::ThreadLocal;
static CONNECTION_MANAGER: Lazy<Pool<ConnectionManager<SqliteConnection>>> =
Lazy::new(|| establish_connection().unwrap());
static DB: Lazy<ThreadLocal<PooledConnection<ConnectionManager<SqliteConnection>>>> =
Lazy::new(|| ThreadLocal::new());
static REGEX_CACHE: Lazy<Arc<Mutex<LruCache<String, Arc<Regex>>>>> =
Lazy::new(|| Arc::new(Mutex::new(LruCache::unbounded())));
embed_migrations!("./migrations");
pub mod functions {
use diesel::sql_types::*;
sql_function!(fn regexp(regex: Text, text: Text) -> Bool);
}
fn establish_connection() -> Result<Pool<ConnectionManager<SqliteConnection>>, Box<dyn Error>> {
let database_folder = home_dir()
.unwrap()
.join("Library/Application Support/com.samdenty.github-icons");
if !database_folder.exists() {
std::fs::create_dir_all(&database_folder)?;
}
let database_url = format!("file:{}/database.db", database_folder.to_string_lossy());
let manager = ConnectionManager::<SqliteConnection>::new(database_url);
let pool = Pool::builder().max_size(30).build(manager)?;
let conn = pool.get()?;
embedded_migrations::run(&conn)?;
functions::regexp::register_impl(&conn, move |regex: String, text: String| {
let mut cache = REGEX_CACHE.lock().unwrap();
let re = cache.get(®ex).cloned().unwrap_or_else(|| {
let re = Arc::new(Regex::new(®ex).unwrap());
cache.put(regex, re.clone());
re
});
re.is_match(&text)
})
.unwrap();
Ok(pool)
}
pub fn db() -> &'static PooledConnection<ConnectionManager<SqliteConnection>> {
DB.get_or(|| CONNECTION_MANAGER.get().unwrap())
}