diff --git a/.travis.yml b/.travis.yml index 09cf8e83b..c931e43ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -60,6 +60,7 @@ script: cd examples/state && cargo check && cd ../.. cd examples/template_tera && cargo check && cd ../.. cd examples/diesel && cargo check && cd ../.. + cd examples/r2d2 && cargo check && cd ../.. cd examples/tls && cargo check && cd ../.. cd examples/websocket-chat && cargo check && cd ../.. cd examples/websocket && cargo check && cd ../.. diff --git a/Cargo.toml b/Cargo.toml index c20ab363f..36b2c5dea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ members = [ "./", "examples/basics", "examples/diesel", + "examples/r2d2", "examples/json", "examples/hello-world", "examples/multipart", diff --git a/examples/r2d2/Cargo.toml b/examples/r2d2/Cargo.toml new file mode 100644 index 000000000..bb91b495c --- /dev/null +++ b/examples/r2d2/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "r2d2-example" +version = "0.1.0" +authors = ["Nikolay Kim "] +workspace = "../.." + +[dependencies] +env_logger = "0.5" +actix = { git = "https://github.com/actix/actix.git/" } +actix-web = { path = "../../" } + +futures = "0.1" +uuid = { version = "0.5", features = ["serde", "v4"] } +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" + +r2d2 = "*" +r2d2_sqlite = "*" +rusqlite = "*" diff --git a/examples/r2d2/src/db.rs b/examples/r2d2/src/db.rs new file mode 100644 index 000000000..6e2ddc09f --- /dev/null +++ b/examples/r2d2/src/db.rs @@ -0,0 +1,41 @@ +//! Db executor actor +use std::io; +use uuid; +use actix_web::*; +use actix::prelude::*; +use r2d2::Pool; +use r2d2_sqlite::SqliteConnectionManager; + + +/// 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/examples/r2d2/src/main.rs b/examples/r2d2/src/main.rs new file mode 100644 index 000000000..2efc64b9f --- /dev/null +++ b/examples/r2d2/src/main.rs @@ -0,0 +1,63 @@ +//! Actix web r2d2 example +extern crate serde; +extern crate serde_json; +extern crate uuid; +extern crate futures; +extern crate actix; +extern crate actix_web; +extern crate env_logger; +extern crate r2d2; +extern crate r2d2_sqlite; +extern crate rusqlite; + +use actix::*; +use actix_web::*; +use futures::future::Future; +use r2d2_sqlite::SqliteConnectionManager; + +mod db; +use db::{CreateUser, DbExecutor}; + + +/// State with DbExecutor address +struct State { + db: Addr, +} + +/// 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(httpcodes::HTTPOk.build().json(user)?), + Err(_) => Ok(httpcodes::HTTPInternalServerError.into()) + } + }) + .responder() +} + +fn main() { + ::std::env::set_var("RUST_LOG", "actix_web=debug"); + let _ = env_logger::init(); + let sys = actix::System::new("r2d2-example"); + + 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 + let _addr = HttpServer::new(move || { + Application::with_state(State{db: addr.clone()}) + // enable logger + .middleware(middleware::Logger::default()) + .resource("/{name}", |r| r.method(Method::GET).a(index))}) + .bind("127.0.0.1:8080").unwrap() + .start(); + + let _ = sys.run(); +} diff --git a/examples/r2d2/test.db b/examples/r2d2/test.db new file mode 100644 index 000000000..3ea0c83d7 Binary files /dev/null and b/examples/r2d2/test.db differ