1
0
mirror of https://github.com/actix/examples synced 2024-11-23 14:31:07 +01:00

fix db/basic

This commit is contained in:
Rob Ede 2022-02-06 08:19:35 +00:00
parent 8ae47c8cda
commit a4d43c0ff8
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
12 changed files with 112 additions and 103 deletions

View File

@ -39,10 +39,11 @@ jobs:
- name: create test db for sqlx
run: |
sudo apt-get update && sudo apt-get install sqlite3
cd database_interactions/sqlx_todo
cp .env.example .env
cat schema.sql | sqlite3 test.db
chmod a+rwx test.db
cargo install sqlx-cli --no-default-features --features=rustls,sqlite
cd basics/todo
sqlx database create
chmod a+rwx todo.db
sqlx migrate run
- name: cargo check
uses: actions-rs/cargo@v1

102
Cargo.lock generated
View File

@ -1258,9 +1258,8 @@ version = "1.0.0"
dependencies = [
"actix-web 4.0.0-rc.2",
"env_logger 0.9.0",
"failure",
"futures",
"num_cpus",
"futures-util",
"log",
"r2d2",
"r2d2_sqlite",
"rusqlite",
@ -2256,7 +2255,7 @@ dependencies = [
"byteorder",
"chrono",
"diesel_derives",
"libsqlite3-sys",
"libsqlite3-sys 0.9.1",
"pq-sys",
"r2d2",
"uuid 0.8.2",
@ -2371,6 +2370,9 @@ name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
dependencies = [
"serde 1.0.136",
]
[[package]]
name = "encoding_rs"
@ -2503,6 +2505,18 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "flume"
version = "0.10.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d04dafd11240188e146b6f6476a898004cace3be31d4ec5e08e216bf4947ac0"
dependencies = [
"futures-core",
"futures-sink",
"pin-project 1.0.10",
"spin 0.9.2",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -3462,9 +3476,19 @@ checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74"
[[package]]
name = "libsqlite3-sys"
version = "0.22.2"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d"
checksum = "0e9eb7b8e152b6a01be6a4a2917248381875758250dc3df5d46caf9250341dda"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "libsqlite3-sys"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58"
dependencies = [
"cc",
"pkg-config",
@ -4622,9 +4646,9 @@ dependencies = [
[[package]]
name = "r2d2_sqlite"
version = "0.18.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d24607049214c5e42d3df53ac1d8a23c34cc6a5eefe3122acb2c72174719959"
checksum = "54ca3c9468a76fc2ad724c486a59682fc362efeac7b18d1c012958bc19f34800"
dependencies = [
"r2d2",
"rusqlite",
@ -5033,15 +5057,15 @@ dependencies = [
[[package]]
name = "rusqlite"
version = "0.25.4"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c4b1eaf239b47034fb450ee9cdedd7d0226571689d8823030c4b6c2cb407152"
checksum = "4ba4d3462c8b2e4d7f4fcfcf2b296dc6b65404fbbc7b63daa37fd485c149daf7"
dependencies = [
"bitflags",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"libsqlite3-sys 0.23.2",
"memchr",
"smallvec",
]
@ -5595,6 +5619,9 @@ name = "spin"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5"
dependencies = [
"lock_api",
]
[[package]]
name = "sqlformat"
@ -5609,9 +5636,9 @@ dependencies = [
[[package]]
name = "sqlx"
version = "0.5.9"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7911b0031a0247af40095838002999c7a52fba29d9739e93326e71a5a1bc9d43"
checksum = "692749de69603d81e016212199d73a2e14ee20e2def7d7914919e8db5d4d48b9"
dependencies = [
"sqlx-core",
"sqlx-macros",
@ -5619,9 +5646,9 @@ dependencies = [
[[package]]
name = "sqlx-core"
version = "0.5.9"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aec89bfaca8f7737439bad16d52b07f1ccd0730520d3bf6ae9d069fe4b641fb1"
checksum = "518be6f6fff5ca76f985d434f9c37f3662af279642acf730388f271dff7b9016"
dependencies = [
"ahash",
"atoi",
@ -5633,22 +5660,25 @@ dependencies = [
"crossbeam-queue",
"crossbeam-utils 0.8.6",
"either",
"flume",
"futures-channel",
"futures-core",
"futures-executor",
"futures-intrusive",
"futures-util",
"hashlink",
"hex",
"indexmap",
"itoa 0.4.8",
"itoa 1.0.1",
"libc",
"libsqlite3-sys",
"libsqlite3-sys 0.23.2",
"log",
"memchr",
"once_cell",
"parking_lot",
"percent-encoding",
"rustls 0.19.1",
"serde 1.0.136",
"sha2 0.9.9",
"smallvec",
"sqlformat",
@ -5659,21 +5689,23 @@ dependencies = [
"url",
"webpki 0.21.4",
"webpki-roots 0.21.1",
"whoami",
]
[[package]]
name = "sqlx-macros"
version = "0.5.9"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "584866c833511b1a152e87a7ee20dee2739746f60c858b3c5209150bc4b466f5"
checksum = "38e45140529cf1f90a5e1c2e561500ca345821a1c513652c8f486bbf07407cc8"
dependencies = [
"dotenv",
"either",
"heck 0.3.3",
"hex",
"once_cell",
"proc-macro2",
"quote",
"serde 1.0.136",
"serde_json",
"sha2 0.9.9",
"sqlx-core",
"sqlx-rt",
@ -5687,27 +5719,11 @@ version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8061cbaa91ee75041514f67a09398c65a64efed72c90151ecd47593bad53da99"
dependencies = [
"actix-rt 2.6.0",
"once_cell",
"tokio 1.16.1",
"tokio-rustls 0.22.0",
]
[[package]]
name = "sqlx_todo"
version = "1.0.0"
dependencies = [
"actix-web 4.0.0-rc.2",
"anyhow",
"dotenv",
"env_logger 0.9.0",
"futures",
"log",
"serde 1.0.136",
"serde_json",
"sqlx",
]
[[package]]
name = "standback"
version = "0.2.17"
@ -6124,13 +6140,13 @@ dependencies = [
"actix-files 0.6.0-beta.16",
"actix-session 0.5.0-beta.7",
"actix-web 4.0.0-rc.2",
"diesel",
"dotenv",
"env_logger 0.9.0",
"futures",
"futures-util",
"log",
"serde 1.0.136",
"serde_json",
"sqlx",
"tera",
]
@ -7070,16 +7086,6 @@ dependencies = [
"tokio-util 0.3.1",
]
[[package]]
name = "whoami"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524b58fa5a20a2fb3014dd6358b70e6579692a56ef6fce928834e488f42f65e8"
dependencies = [
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "widestring"
version = "0.4.3"

View File

@ -81,7 +81,7 @@ async fn create_something(
async fn main() -> io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
log::info!("starting HTTP serer at http://localhost:8080");
log::info!("starting HTTP server at http://localhost:8080");
HttpServer::new(|| {
App::new()

View File

@ -27,7 +27,7 @@ async fn main() -> io::Result<()> {
.await
.expect("Failed to create pool");
log::info!("starting HTTP serer at http://localhost:8080");
log::info!("starting HTTP server at http://localhost:8080");
HttpServer::new(move || {
log::debug!("Constructing the App");

View File

@ -0,0 +1,2 @@
weather.db
weather.db-*

View File

@ -4,13 +4,13 @@ version = "1.0.0"
edition = "2021"
[dependencies]
actix-web = "4.0.0-rc.1"
env_logger = "0.9.0"
failure = "0.1.7"
futures = "0.3.1"
num_cpus = "1.13"
r2d2 = "0.8.2"
r2d2_sqlite = "0.18.0"
rusqlite = "0.25.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
actix-web = "4.0.0-rc.2"
env_logger = "0.9"
futures-util = { version = "0.3", default-features = false, features = ["std"] }
log = "0.4"
r2d2 = "0.8"
r2d2_sqlite = "0.19"
rusqlite = "0.26"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

View File

@ -1,5 +1,4 @@
use actix_web::{error::InternalError, http::StatusCode, web};
use failure::Error;
use actix_web::{error, web, Error};
use rusqlite::Statement;
use serde::{Deserialize, Serialize};
use std::{thread::sleep, time::Duration};
@ -22,26 +21,26 @@ pub enum Queries {
GetTopTenColdestMonths,
}
pub async fn execute(
pool: &Pool,
query: Queries,
) -> Result<Vec<WeatherAgg>, InternalError<Error>> {
pub async fn execute(pool: &Pool, query: Queries) -> Result<Vec<WeatherAgg>, Error> {
let pool = pool.clone();
let conn = web::block(move || pool.get())
.await?
.map_err(error::ErrorInternalServerError)?;
web::block(move || {
// simulate an expensive query, see comments at top of main.rs
sleep(Duration::from_secs(2));
let result = match query {
Queries::GetTopTenHottestYears => get_hottest_years(pool.get()?),
Queries::GetTopTenColdestYears => get_coldest_years(pool.get()?),
Queries::GetTopTenHottestMonths => get_hottest_months(pool.get()?),
Queries::GetTopTenColdestMonths => get_coldest_months(pool.get()?),
};
result.map_err(Error::from)
match query {
Queries::GetTopTenHottestYears => get_hottest_years(conn),
Queries::GetTopTenColdestYears => get_coldest_years(conn),
Queries::GetTopTenHottestMonths => get_hottest_months(conn),
Queries::GetTopTenColdestMonths => get_coldest_months(conn),
}
})
.await
.unwrap()
.map_err(|e| InternalError::new(e, StatusCode::INTERNAL_SERVER_ERROR))
.await?
.map_err(error::ErrorInternalServerError)
}
fn get_hottest_years(conn: Connection) -> WeatherAggResult {

View File

@ -1,28 +1,27 @@
/* Actix-Web Asynchronous Database Example
//! Actix Web Asynchronous Database Example
//!
//! This project illustrates expensive and blocking database requests that runs
//! in a thread-pool using `web::block` with two examples:
//!
//! 1. An asynchronous handler that executes 4 queries in *sequential order*,
//! collecting the results and returning them as a single serialized json object
//!
//! 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
//! improvement with parallelism more obvious.
This project illustrates expensive and blocking database requests that runs
in a thread-pool using `web::block` with two examples:
1. An asynchronous handler that executes 4 queries in *sequential order*,
collecting the results and returning them as a single serialized json object
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
improvement with parallelism more obvious.
*/
use std::io;
use actix_web::{middleware, web, App, Error as AWError, HttpResponse, HttpServer};
use futures::future::join_all;
use futures_util::future::join_all;
use r2d2_sqlite::{self, SqliteConnectionManager};
mod db;
use db::{Pool, Queries};
/// Version 1: Calls 4 queries in sequential order, as an asynchronous handler
#[allow(clippy::eval_order_dependence)] // it's FP?
async fn asyncio_weather(db: web::Data<Pool>) -> Result<HttpResponse, AWError> {
let result = vec![
db::execute(&db, Queries::GetTopTenHottestYears).await?,
@ -50,14 +49,15 @@ async fn parallel_weather(db: web::Data<Pool>) -> Result<HttpResponse, AWError>
#[actix_web::main]
async fn main() -> io::Result<()> {
std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init();
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
// Start N db executor actors (N = number of cores avail)
// connect to SQLite DB
let manager = SqliteConnectionManager::file("weather.db");
let pool = Pool::new(manager).unwrap();
// Start http server
log::info!("starting HTTP server at http://localhost:8080");
// start HTTP server
HttpServer::new(move || {
App::new()
// store db pool as Data object
@ -71,7 +71,8 @@ async fn main() -> io::Result<()> {
.route(web::get().to(parallel_weather)),
)
})
.bind("127.0.0.1:8080")?
.bind(("127.0.0.1", 8080))?
.workers(2)
.run()
.await
}

View File

@ -69,7 +69,7 @@ async fn main() -> std::io::Result<()> {
let forward_url = Url::parse(&forward_url).unwrap();
log::info!(
"starting HTTP serer at http://{}:{}",
"starting HTTP server at http://{}:{}",
&args.listen_addr,
args.listen_port
);

View File

@ -8,7 +8,7 @@ async fn index(req: HttpRequest) -> &'static str {
}
async fn run_app(tx: mpsc::Sender<ServerHandle>) -> std::io::Result<()> {
log::info!("starting HTTP serer at http://localhost:8080");
log::info!("starting HTTP server at http://localhost:8080");
// srv is server controller type, `dev::Server`
let server = HttpServer::new(|| {

View File

@ -41,7 +41,7 @@ async fn main() -> std::io::Result<()> {
let client_tls_config = Arc::new(rustls_config());
log::info!("starting HTTP serer at http://localhost:8080");
log::info!("starting HTTP server at http://localhost:8080");
HttpServer::new(move || {
// create client _inside_ `HttpServer::new` closure to have one per worker thread

0
weather.db Normal file
View File