diff --git a/Cargo.lock b/Cargo.lock index a918f5d..d868b63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,6 +113,7 @@ checksum = "f7a532c1f99a0f596f6960a60d1e119e91582b24b39e2d83a190e61262c3ef0c" dependencies = [ "diesel_derives", "libsqlite3-sys", + "r2d2", "time", ] @@ -798,6 +799,29 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + [[package]] name = "pin-project" version = "1.1.0" @@ -898,6 +922,26 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "relm4" version = "0.6.0" @@ -993,6 +1037,15 @@ dependencies = [ "relm4-icons", ] +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +dependencies = [ + "parking_lot", +] + [[package]] name = "scopeguard" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 3c11b50..43c8290 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ gtk = { version = "0.6.6", package = "gtk4" } relm4 = { version = "0.6.0", features = ["libadwaita"] } relm4-components = "0.6.0" relm4-icons = { version = "0.6.0", features = ["plus", "minus"] } -diesel = { version = "2.1.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } +diesel = { version = "2.1.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35", "r2d2"] } libsqlite3-sys = { version = "0.26.0", features = ["bundled"] } dotenvy = "0.15" nom = "7.1.3" diff --git a/src/bin/add_sample.rs b/src/bin/add_sample.rs index fbb7034..bdefed3 100644 --- a/src/bin/add_sample.rs +++ b/src/bin/add_sample.rs @@ -5,7 +5,7 @@ fn main() { let suggestions = TagSuggestions::read_from_file("tag_terms.txt").expect("expected tag file to load"); - let connection = &mut establish_connection(); + let connection = &mut get_connection_pool().get().expect("Expected a connection"); let file_str = env::args().nth(1).expect("Need just one argument."); let tags = suggestions.get_suggestions(&file_str); diff --git a/src/bin/create_library.rs b/src/bin/create_library.rs index 75acbb1..6b665da 100644 --- a/src/bin/create_library.rs +++ b/src/bin/create_library.rs @@ -2,7 +2,7 @@ use sample_amp::*; use std::io::{stdin, stdout, Write}; fn main() { - let connection = &mut establish_connection(); + let connection = &mut get_connection_pool().get().expect("Expected a connection."); let mut name = String::new(); diff --git a/src/bin/list_samples.rs b/src/bin/list_samples.rs index 0a7c70c..1e442b6 100644 --- a/src/bin/list_samples.rs +++ b/src/bin/list_samples.rs @@ -1,8 +1,8 @@ use itertools::Itertools; -use sample_amp::{establish_connection, list_tags}; +use sample_amp::{get_connection_pool, list_tags}; fn main() { - let connection = &mut establish_connection(); + let connection = &mut get_connection_pool().get().expect("Expected a connection"); println!( "Found tags: {}", list_tags(connection).iter().map(|t| &t.name).join(", ") diff --git a/src/bin/list_tags.rs b/src/bin/list_tags.rs index 0a7c70c..da7582d 100644 --- a/src/bin/list_tags.rs +++ b/src/bin/list_tags.rs @@ -1,8 +1,8 @@ use itertools::Itertools; -use sample_amp::{establish_connection, list_tags}; +use sample_amp::{get_connection_pool, list_tags}; fn main() { - let connection = &mut establish_connection(); + let connection = &mut get_connection_pool().get().expect("Expected a connection."); println!( "Found tags: {}", list_tags(connection).iter().map(|t| &t.name).join(", ") diff --git a/src/bin/show_libraries.rs b/src/bin/show_libraries.rs index 9ccae43..8fd345b 100644 --- a/src/bin/show_libraries.rs +++ b/src/bin/show_libraries.rs @@ -5,7 +5,7 @@ use sample_amp::*; fn main() { use self::schema::libraries::dsl::*; - let connection = &mut establish_connection(); + let connection = &mut get_connection_pool().get().expect("Expected a connection"); let results = libraries .limit(5) .select(Library::as_select()) diff --git a/src/lib.rs b/src/lib.rs index 9ab9099..4666ef4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,7 @@ -use diesel::prelude::*; +use diesel::{ + prelude::*, + r2d2::{ConnectionManager, Pool}, +}; use dotenvy::dotenv; use models::{NewSample, Sample, Tag}; use std::{env, path::Path}; @@ -9,12 +12,17 @@ pub mod models; pub mod schema; pub mod tag_terms; -pub fn establish_connection() -> SqliteConnection { +pub fn get_connection_pool() -> Pool> { dotenv().ok(); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - SqliteConnection::establish(&database_url) - .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) + + let manager = ConnectionManager::::new(database_url); + + Pool::builder() + .test_on_check_out(true) + .build(manager) + .expect("Could not build connection pool") } pub fn create_library(conn: &mut SqliteConnection, name: &str) -> Library { diff --git a/src/main.rs b/src/main.rs index 4d62465..2ae5414 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use diesel::prelude::*; +use diesel::r2d2::{ConnectionManager, Pool}; use gtk::gdk::Display; use gtk::prelude::*; use relm4::{factory::FactoryVecDeque, prelude::*}; @@ -8,7 +9,7 @@ mod sample_list; use library_list::LibraryListItem; mod app_msg; use app_msg::AppMsg; -use sample_amp::establish_connection; +use sample_amp::get_connection_pool; use sample_amp::models::Library; use sample_amp::schema::libraries; @@ -17,7 +18,7 @@ use crate::sample_list::SampleListModel; struct AppModel { sample_list: Controller, libraries: FactoryVecDeque, - connection: SqliteConnection, + pool: Pool>, } #[relm4::component] @@ -33,7 +34,7 @@ impl SimpleComponent for AppModel { sender: ComponentSender, ) -> relm4::ComponentParts { let mut model = AppModel { - connection: establish_connection(), + pool: get_connection_pool(), libraries: FactoryVecDeque::new(gtk::ListBox::default(), sender.input_sender()), sample_list: SampleListModel::builder().launch(()).detach(), }; @@ -43,7 +44,7 @@ impl SimpleComponent for AppModel { // todo: cleaner let library_results = libraries::dsl::libraries .select(Library::as_select()) - .load(&mut model.connection) + .load(&mut model.pool.get().expect("Expected a connection.")) .expect("Error loading libraries"); model.libraries.guard().push_back("All".to_string());