From 10731e43c6ffe5e9138009af27f35feb25922084 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 10:04:41 -0800 Subject: [PATCH] convert r2d2 example --- basics/Cargo.toml | 1 - r2d2/Cargo.toml | 19 +++++----- r2d2/src/db.rs | 44 ----------------------- r2d2/src/main.rs | 90 +++++++++++++++++++++-------------------------- 4 files changed, 48 insertions(+), 106 deletions(-) delete mode 100644 r2d2/src/db.rs diff --git a/basics/Cargo.toml b/basics/Cargo.toml index ddb7736e..4e288328 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" [dependencies] actix-rt = "0.1" - actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-staticfiles = { git="https://github.com/actix/actix-web.git", branch = "1.0" } diff --git a/r2d2/Cargo.toml b/r2d2/Cargo.toml index 884d84c4..b9f8de7c 100644 --- a/r2d2/Cargo.toml +++ b/r2d2/Cargo.toml @@ -2,20 +2,17 @@ name = "r2d2-example" version = "0.1.0" authors = ["Nikolay Kim "] +edition = "2018" workspace = "../" [dependencies] -env_logger = "0.5" - -actix = "0.7" -actix-web = "0.7" +actix-rt = "0.1" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } futures = "0.1" -uuid = { version = "0.5", features = ["serde", "v4"] } -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" +env_logger = "0.6" +uuid = { version = "0.7", features = ["v4"] } -r2d2 = "*" -r2d2_sqlite = "*" -rusqlite = "*" +r2d2 = "0.8" +r2d2_sqlite = "0.8" +rusqlite = "0.16" diff --git a/r2d2/src/db.rs b/r2d2/src/db.rs deleted file mode 100644 index 5df9b3ff..00000000 --- a/r2d2/src/db.rs +++ /dev/null @@ -1,44 +0,0 @@ -//! Db executor actor -use actix::prelude::*; -use actix_web::*; -use r2d2::Pool; -use r2d2_sqlite::SqliteConnectionManager; -use std::io; -use uuid; - -/// This is db executor actor. We are going to run 3 of them in parallel. -pub struct DbExecutor(pub Pool); - -/// This is only message that this actor can handle, but it is easy to extend -/// number of messages. -pub struct CreateUser { - pub name: String, -} - -impl Message for CreateUser { - type Result = Result; -} - -impl Actor for DbExecutor { - type Context = SyncContext; -} - -impl Handler for DbExecutor { - type Result = Result; - - fn handle(&mut self, msg: CreateUser, _: &mut Self::Context) -> Self::Result { - let conn = self.0.get().unwrap(); - - let uuid = format!("{}", uuid::Uuid::new_v4()); - conn.execute( - "INSERT INTO users (id, name) VALUES ($1, $2)", - &[&uuid, &msg.name], - ).unwrap(); - - Ok(conn - .query_row("SELECT name FROM users WHERE id=$1", &[&uuid], |row| { - row.get(0) - }) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "db error"))?) - } -} diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index e3cdb421..c594253f 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -1,68 +1,58 @@ //! Actix web r2d2 example -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate futures; -extern crate r2d2; -extern crate r2d2_sqlite; -extern crate rusqlite; -extern crate serde; -extern crate serde_json; -extern crate uuid; +use std::io; -use actix::prelude::*; use actix_web::{ - http, middleware, server, App, AsyncResponder, Error, HttpRequest, HttpResponse, + blocking, extract::Path, web, App, Error, HttpResponse, HttpServer, State, }; -use futures::future::Future; +use futures::Future; +use r2d2::Pool; use r2d2_sqlite::SqliteConnectionManager; +use uuid; -mod db; -use db::{CreateUser, DbExecutor}; +/// Async request handler. Ddb pool is stored in application state. +fn index( + path: Path, + db: State>, +) -> impl Future { + // execute sync code in threadpool + blocking::run(move || { + let conn = db.get().unwrap(); -/// State with DbExecutor address -struct State { - db: Addr, + let uuid = format!("{}", uuid::Uuid::new_v4()); + conn.execute( + "INSERT INTO users (id, name) VALUES ($1, $2)", + &[&uuid, &path.into_inner()], + ) + .unwrap(); + + conn.query_row("SELECT name FROM users WHERE id=$1", &[&uuid], |row| { + row.get::<_, String>(0) + }) + }) + .then(|res| match res { + Ok(user) => Ok(HttpResponse::Ok().json(user)), + Err(_) => Ok(HttpResponse::InternalServerError().into()), + }) } -/// Async request handler -fn index(req: &HttpRequest) -> Box> { - let name = &req.match_info()["name"]; - - req.state() - .db - .send(CreateUser { - name: name.to_owned(), - }) - .from_err() - .and_then(|res| match res { - Ok(user) => Ok(HttpResponse::Ok().json(user)), - Err(_) => Ok(HttpResponse::InternalServerError().into()), - }) - .responder() -} - -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=debug"); +fn main() -> io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=debug"); env_logger::init(); - let sys = actix::System::new("r2d2-example"); + let sys = actix_rt::System::new("r2d2-example"); // r2d2 pool let manager = SqliteConnectionManager::file("test.db"); let pool = r2d2::Pool::new(manager).unwrap(); - // Start db executor actors - let addr = SyncArbiter::start(3, move || DbExecutor(pool.clone())); - - // Start http server - server::new(move || { - App::with_state(State{db: addr.clone()}) - // enable logger - .middleware(middleware::Logger::default()) - .resource("/{name}", |r| r.method(http::Method::GET).a(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + // start http server + HttpServer::new(move || { + App::new() + .state(pool.clone()) // <- store db pool in app state + .resource("/{name}", |r| r.route(web::get().to_async(index))) + }) + .bind("127.0.0.1:8080")? + .start(); let _ = sys.run(); + Ok(()) }