Merge branch 'actix_2'
This commit is contained in:
commit
9eb85584ea
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
docker-compose up -d --build --remove-orphans --no-deps
|
File diff suppressed because it is too large
Load Diff
|
@ -2,18 +2,24 @@
|
||||||
name = "torrents-csv-service"
|
name = "torrents-csv-service"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Dessalines <happydooby@gmail.com>"]
|
authors = ["Dessalines <happydooby@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "1.0"
|
actix-rt = "1.0.0"
|
||||||
actix-files = "0.1.7"
|
actix-web = "2.0.0"
|
||||||
|
actix-files = "0.2.1"
|
||||||
|
env_logger = "0.7.1"
|
||||||
|
|
||||||
serde = "*"
|
serde = "*"
|
||||||
serde_json = "*"
|
serde_json = "1.0.44"
|
||||||
serde_derive = "*"
|
serde_derive = "*"
|
||||||
time = "*"
|
|
||||||
|
futures = "0.3.1"
|
||||||
failure = "*"
|
failure = "*"
|
||||||
r2d2 = "0.8.6"
|
|
||||||
r2d2_sqlite = "0.12.0"
|
r2d2 = "0.8"
|
||||||
|
r2d2_sqlite = "0.13"
|
||||||
|
|
||||||
[dependencies.rusqlite]
|
[dependencies.rusqlite]
|
||||||
version = "0.20.0"
|
version = "0.21.0"
|
||||||
features = ["bundled"]
|
features = ["bundled"]
|
||||||
|
|
|
@ -5,7 +5,6 @@ extern crate serde_json;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate rusqlite;
|
extern crate rusqlite;
|
||||||
extern crate time;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
extern crate r2d2;
|
extern crate r2d2;
|
||||||
|
@ -13,33 +12,40 @@ extern crate r2d2_sqlite;
|
||||||
|
|
||||||
use actix_files as fs;
|
use actix_files as fs;
|
||||||
use actix_files::NamedFile;
|
use actix_files::NamedFile;
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
use actix_web::{middleware, web, App, HttpResponse, HttpServer};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use r2d2_sqlite::SqliteConnectionManager;
|
use r2d2_sqlite::SqliteConnectionManager;
|
||||||
use rusqlite::params;
|
use rusqlite::params;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::cmp;
|
||||||
|
use std::io;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
fn main() {
|
#[actix_rt::main]
|
||||||
|
async fn main() -> io::Result<()> {
|
||||||
println!("Access me at {}", endpoint());
|
println!("Access me at {}", endpoint());
|
||||||
|
std::env::set_var("RUST_LOG", "actix_web=debug");
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
let manager = SqliteConnectionManager::file(torrents_db_file());
|
let manager = SqliteConnectionManager::file(torrents_db_file());
|
||||||
let pool = r2d2::Pool::builder().max_size(15).build(manager).unwrap();
|
let pool = r2d2::Pool::builder().max_size(15).build(manager).unwrap();
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
.route("/", web::get().to(index))
|
|
||||||
.service(fs::Files::new("/static", front_end_dir()))
|
|
||||||
.data(pool.clone())
|
.data(pool.clone())
|
||||||
.route("/service/search", web::get().to_async(search))
|
.wrap(middleware::Logger::default())
|
||||||
|
.service(fs::Files::new("/static", front_end_dir()))
|
||||||
|
.route("/", web::get().to(index))
|
||||||
|
.route("/service/search", web::get().to(search))
|
||||||
})
|
})
|
||||||
.bind(endpoint())
|
.keep_alive(None)
|
||||||
.unwrap()
|
.bind(endpoint())?
|
||||||
.run()
|
.run()
|
||||||
.unwrap()
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn index() -> Result<NamedFile, actix_web::error::Error> {
|
async fn index() -> Result<NamedFile, actix_web::error::Error> {
|
||||||
Ok(NamedFile::open(front_end_dir() + "/index.html")?)
|
Ok(NamedFile::open(front_end_dir() + "/index.html")?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,32 +69,35 @@ struct SearchQuery {
|
||||||
type_: Option<String>,
|
type_: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search(
|
async fn search(
|
||||||
db: web::Data<r2d2::Pool<SqliteConnectionManager>>,
|
db: web::Data<r2d2::Pool<SqliteConnectionManager>>,
|
||||||
query: web::Query<SearchQuery>,
|
query: web::Query<SearchQuery>,
|
||||||
) -> HttpResponse {
|
) -> Result<HttpResponse, actix_web::Error> {
|
||||||
|
|
||||||
if query.q.is_empty() {
|
let res = web::block(move || {
|
||||||
return HttpResponse::BadRequest()
|
let conn = db.get().unwrap();
|
||||||
.header("Access-Control-Allow-Origin", "*")
|
search_query(query, conn)
|
||||||
.content_type("application/json")
|
})
|
||||||
.body(format!("{{\"error\": \"{}\"}}", "Empty query".to_string()));
|
.await
|
||||||
}
|
.map(|body| HttpResponse::Ok()
|
||||||
|
|
||||||
let conn = db.get().unwrap();
|
|
||||||
|
|
||||||
HttpResponse::Ok()
|
|
||||||
.header("Access-Control-Allow-Origin", "*")
|
.header("Access-Control-Allow-Origin", "*")
|
||||||
.content_type("application/json")
|
.json(body))
|
||||||
.body(search_query(query, conn).unwrap())
|
.map_err(|e|
|
||||||
|
actix_web::error::ErrorBadRequest(e))?;
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_query(
|
fn search_query(
|
||||||
query: web::Query<SearchQuery>,
|
query: web::Query<SearchQuery>,
|
||||||
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
||||||
) -> Result<String, serde_json::Error> {
|
) -> Result<Value, Error> {
|
||||||
|
|
||||||
|
if query.q.is_empty() || query.q.trim() == "*" {
|
||||||
|
return Err(format_err!("{{\"error\": \"{}\"}}", "Empty query".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
let page = query.page.unwrap_or(1);
|
let page = query.page.unwrap_or(1);
|
||||||
let size = query.size.unwrap_or(10);
|
let size = cmp::min(100, query.size.unwrap_or(10));
|
||||||
let type_ = query.type_.as_ref().map_or("torrent", String::deref);
|
let type_ = query.type_.as_ref().map_or("torrent", String::deref);
|
||||||
let offset = size * (page - 1);
|
let offset = size * (page - 1);
|
||||||
|
|
||||||
|
@ -97,13 +106,15 @@ fn search_query(
|
||||||
query.q, type_, page, size
|
query.q, type_, page, size
|
||||||
);
|
);
|
||||||
|
|
||||||
if type_ == "file" {
|
let res = if type_ == "file" {
|
||||||
let results = torrent_file_search(conn, &query.q, size, offset).unwrap();
|
let results = torrent_file_search(conn, &query.q, size, offset)?;
|
||||||
serde_json::to_string(&results)
|
serde_json::to_value(&results).unwrap()
|
||||||
} else {
|
} else {
|
||||||
let results = torrent_search(conn, &query.q, size, offset).unwrap();
|
let results = torrent_search(conn, &query.q, size, offset)?;
|
||||||
serde_json::to_string(&results)
|
serde_json::to_value(&results).unwrap()
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
@ -204,14 +215,15 @@ fn torrent_file_search(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use time::PreciseTime;
|
use r2d2_sqlite::SqliteConnectionManager;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let start = PreciseTime::now();
|
let manager = SqliteConnectionManager::file(super::torrents_db_file());
|
||||||
let results = super::torrent_search("sherlock", 10, 0);
|
let pool = r2d2::Pool::builder().max_size(15).build(manager).unwrap();
|
||||||
assert!(results.len() > 2);
|
let conn = pool.get().unwrap();
|
||||||
let end = PreciseTime::now();
|
let results = super::torrent_search(conn, "sherlock", 10, 0);
|
||||||
println!("Query took {} seconds.", start.to(end));
|
assert!(results.unwrap().len() > 2);
|
||||||
|
// println!("Query took {:?} seconds.", end - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue