diff --git a/async_db/src/main.rs b/async_db/src/main.rs index 99cc6f8d..78ab4cc7 100644 --- a/async_db/src/main.rs +++ b/async_db/src/main.rs @@ -8,7 +8,7 @@ This project illustrates two examples: 2. An asynchronous handler that executes 4 queries in *parallel*, collecting the results and returning them as a single serialized json object - Note: The use of sleep(Duration::from_secs(2)); in db.rs is to make performance + Note: The use of sleep(Duration::from_secs(2)); in db.rs is to make performance improvement with parallelism more obvious. */ use std::io; diff --git a/async_ex2/Cargo.toml b/async_ex2/Cargo.toml index ace032b8..2cf14aa0 100644 --- a/async_ex2/Cargo.toml +++ b/async_ex2/Cargo.toml @@ -7,7 +7,7 @@ workspace = ".." [dependencies] actix-rt = "0.2.2" -actix-web = { version="1.0.0-alpha.4", features=["ssl"] } +actix-web = { version="1.0.0-beta.1", features=["ssl"] } actix-multipart = { git="https://github.com/actix/actix-web.git" } bytes = "0.4.12" env_logger = "0.6.1" diff --git a/async_ex2/src/appconfig.rs b/async_ex2/src/appconfig.rs index e38629a6..9393e129 100644 --- a/async_ex2/src/appconfig.rs +++ b/async_ex2/src/appconfig.rs @@ -2,7 +2,7 @@ use actix_web::{error, web}; use crate::handlers::{parts, products}; -pub fn config_app(cfg: &mut web::RouterConfig) { +pub fn config_app(cfg: &mut web::ServiceConfig) { // domain includes: /products/{product_id}/parts/{part_id} cfg.service( web::scope("/products") diff --git a/multipart/src/main.rs b/multipart/src/main.rs index 5505af8e..aa3c8b97 100644 --- a/multipart/src/main.rs +++ b/multipart/src/main.rs @@ -13,20 +13,33 @@ pub struct AppState { pub fn save_file(field: Field) -> impl Future { let file_path_string = "upload.png"; - let mut file = match fs::File::create(file_path_string) { + let file = match fs::File::create(file_path_string) { Ok(file) => file, Err(e) => return Either::A(err(error::ErrorInternalServerError(e))), }; Either::B( field - .fold(0i64, move |acc, bytes| { - file.write_all(bytes.as_ref()) - .map(|_| acc + bytes.len() as i64) - .map_err(|e| { - println!("file.write_all failed: {:?}", e); - MultipartError::Payload(error::PayloadError::Io(e)) - }) + .fold((file, 0i64), move |(mut file, mut acc), bytes| { + // fs operations are blocking, we have to execute writes + // on threadpool + web::block(move || { + acc += file + .write_all(bytes.as_ref()) + .map(|_| acc + bytes.len() as i64) + .map_err(|e| { + println!("file.write_all failed: {:?}", e); + MultipartError::Payload(error::PayloadError::Io(e)) + })?; + Ok((file, acc)) + }) + .map_err(|e: error::BlockingError| { + match e { + error::BlockingError::Error(e) => e, + error::BlockingError::Canceled => MultipartError::Incomplete, + } + }) }) + .map(|(_, acc)| acc) .map_err(|e| { println!("save_file failed, {:?}", e); error::ErrorInternalServerError(e)