Adding connection pool.

main
Heretic 10 months ago
parent 296b15e5a7
commit cd07888b03

73
Cargo.lock generated

@ -420,25 +420,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.1.6" version = "0.1.6"
@ -846,6 +827,15 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "nanoid"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8"
dependencies = [
"rand",
]
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.16.0" version = "1.16.0"
@ -948,6 +938,28 @@ dependencies = [
"proc-macro2", "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 = "r2d2_sqlite_pool"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c211b97022a76440bd16521bba1abf82398218ade33d96813c5776bf8baf9722"
dependencies = [
"nanoid",
"r2d2",
"rusqlite",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -1064,6 +1076,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[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]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@ -1265,17 +1286,6 @@ dependencies = [
"syn 2.0.27", "syn 2.0.27",
] ]
[[package]]
name = "tokio-rusqlite"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7aa66395f5ff117faee90c9458232c936405f9227ad902038000b74b3bc1feac"
dependencies = [
"crossbeam-channel",
"rusqlite",
"tokio",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.8" version = "0.7.8"
@ -1298,12 +1308,13 @@ dependencies = [
"actix-web", "actix-web",
"anyhow", "anyhow",
"env_logger", "env_logger",
"r2d2",
"r2d2_sqlite_pool",
"rusqlite", "rusqlite",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"tokio", "tokio",
"tokio-rusqlite",
"uuid", "uuid",
] ]

@ -15,9 +15,10 @@ serde_derive = "1.0.163"
anyhow = "1.0.71" anyhow = "1.0.71"
tokio-rusqlite = "0.4.0"
tokio = { version = "1.28.1", features = ["full"] } tokio = { version = "1.28.1", features = ["full"] }
uuid = { version = "1.4.1", features = ["v4", "fast-rng"] } uuid = { version = "1.4.1", features = ["v4", "fast-rng"] }
r2d2_sqlite_pool = "0.1.1"
r2d2 = "0.8.10"
[dependencies.rusqlite] [dependencies.rusqlite]
version = "0.29.0" version = "0.29.0"
features = ["bundled"] features = ["bundled"]

@ -13,22 +13,29 @@ use actix_web::{
HttpServer, HttpServer,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use r2d2::{Pool, PooledConnection};
use r2d2_sqlite_pool::SqliteConnectionManager;
use rusqlite::params; use rusqlite::params;
use std::{cmp, env, io, ops::Deref, path::Path}; use std::{cmp, env, io, ops::Deref};
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tokio_rusqlite::Connection;
use uuid::Uuid; use uuid::Uuid;
const DEFAULT_SIZE: usize = 25; const DEFAULT_SIZE: usize = 25;
type Conn = PooledConnection<SqliteConnectionManager>;
struct MyAppData { struct MyAppData {
etag: String, etag: String,
pool: Pool<SqliteConnectionManager>,
} }
#[actix_web::main] #[actix_web::main]
async fn main() -> io::Result<()> { async fn main() -> io::Result<()> {
let manager = SqliteConnectionManager::file(torrents_db_file());
let pool = r2d2::Pool::new(manager).unwrap();
let my_app_data = Data::new(Mutex::new(MyAppData { let my_app_data = Data::new(Mutex::new(MyAppData {
etag: Uuid::new_v4().to_string(), etag: Uuid::new_v4().to_string(),
pool,
})); }));
println!("Access me at {}", endpoint()); println!("Access me at {}", endpoint());
std::env::set_var("RUST_LOG", "actix_web=debug"); std::env::set_var("RUST_LOG", "actix_web=debug");
@ -68,11 +75,8 @@ async fn search(
) -> Result<HttpResponse, actix_web::Error> { ) -> Result<HttpResponse, actix_web::Error> {
let my_app_data = data.lock().await; let my_app_data = data.lock().await;
let etag = my_app_data.etag.clone(); let etag = my_app_data.etag.clone();
let conn = Connection::open(Path::new(&torrents_db_file())) let conn = my_app_data.pool.get().unwrap();
.await
.map_err(actix_web::error::ErrorBadRequest)?;
let res = search_query(query, conn) let res = search_query(query, conn)
.await
.map(|body| { .map(|body| {
HttpResponse::Ok() HttpResponse::Ok()
.append_header(("Access-Control-Allow-Origin", "*")) .append_header(("Access-Control-Allow-Origin", "*"))
@ -84,7 +88,7 @@ async fn search(
Ok(res) Ok(res)
} }
async fn search_query(query: web::Query<SearchQuery>, conn: Connection) -> Result<Vec<Torrent>> { fn search_query(query: web::Query<SearchQuery>, conn: Conn) -> Result<Vec<Torrent>> {
let q = query.q.trim(); let q = query.q.trim();
if q.is_empty() || q.len() < 3 || q == "2020" { if q.is_empty() || q.len() < 3 || q == "2020" {
return Err(anyhow!("{{\"error\": \"{}\"}}", "Empty query".to_string())); return Err(anyhow!("{{\"error\": \"{}\"}}", "Empty query".to_string()));
@ -97,7 +101,7 @@ async fn search_query(query: web::Query<SearchQuery>, conn: Connection) -> Resul
println!("query = {q}, type = {type_}, page = {page}, size = {size}"); println!("query = {q}, type = {type_}, page = {page}, size = {size}");
torrent_search(conn, q, size, offset).await torrent_search(conn, q, size, offset)
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -112,39 +116,27 @@ struct Torrent {
scraped_date: u32, scraped_date: u32,
} }
async fn torrent_search( fn torrent_search(conn: Conn, query: &str, size: usize, offset: usize) -> Result<Vec<Torrent>> {
conn: Connection,
query: &str,
size: usize,
offset: usize,
) -> Result<Vec<Torrent>> {
let q = query.to_owned(); let q = query.to_owned();
let res = conn let stmt_str = "select * from torrent where name like '%' || ?1 || '%' limit ?2, ?3";
.call(move |conn| { let mut stmt = conn.prepare(stmt_str)?;
let stmt_str = "select * from torrent where name like '%' || ?1 || '%' limit ?2, ?3"; let torrents = stmt
.query_map(
let mut stmt = conn.prepare(stmt_str)?; params![q.replace(' ', "%"), offset.to_string(), size.to_string(),],
let torrents = stmt |row| {
.query_map( Ok(Torrent {
params![q.replace(' ', "%"), offset.to_string(), size.to_string(),], infohash: row.get(0)?,
|row| { name: row.get(1)?,
Ok(Torrent { size_bytes: row.get(2)?,
infohash: row.get(0)?, created_unix: row.get(3)?,
name: row.get(1)?, seeders: row.get(4)?,
size_bytes: row.get(2)?, leechers: row.get(5)?,
created_unix: row.get(3)?, completed: row.get(6)?,
seeders: row.get(4)?, scraped_date: row.get(7)?,
leechers: row.get(5)?, })
completed: row.get(6)?, },
scraped_date: row.get(7)?, )?
}) .collect::<Result<Vec<Torrent>, rusqlite::Error>>()?;
},
)? Ok(torrents)
.collect::<Result<Vec<Torrent>, rusqlite::Error>>()?;
Ok::<_, rusqlite::Error>(torrents)
})
.await?;
Ok(res)
} }

Loading…
Cancel
Save