mirror of
https://github.com/actix/examples
synced 2025-02-02 09:39:03 +01:00
update rusqlite and r2d2_sqlite in async_db and r2d2 (#148)
* upgrade rusqlite to 0.18 * add note about async_db blocking and running in thread pool * idiomatic async_db - DRY - Iterator::collect + return type - note about why we are sleeping * remove r2d2/test.db
This commit is contained in:
parent
817a61855d
commit
78a753a06a
@ -14,7 +14,7 @@ failure = "0.1.1"
|
|||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
num_cpus = "1.10.0"
|
num_cpus = "1.10.0"
|
||||||
r2d2 = "0.8.2"
|
r2d2 = "0.8.2"
|
||||||
r2d2_sqlite = "0.8.0"
|
r2d2_sqlite = "0.10"
|
||||||
rusqlite = "0.16"
|
rusqlite = "0.18"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -3,12 +3,13 @@ use failure::Error;
|
|||||||
use futures::{Future, TryFutureExt};
|
use futures::{Future, TryFutureExt};
|
||||||
use r2d2;
|
use r2d2;
|
||||||
use r2d2_sqlite;
|
use r2d2_sqlite;
|
||||||
use rusqlite::NO_PARAMS;
|
use rusqlite::{Statement, NO_PARAMS};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{thread::sleep, time::Duration};
|
use std::{thread::sleep, time::Duration};
|
||||||
|
|
||||||
pub type Pool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
|
pub type Pool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
|
||||||
pub type Connection = r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
pub type Connection = r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
||||||
|
type WeatherAggResult = Result<Vec<WeatherAgg>, rusqlite::Error>;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum WeatherAgg {
|
pub enum WeatherAgg {
|
||||||
@ -28,115 +29,96 @@ pub fn execute(
|
|||||||
query: Queries,
|
query: Queries,
|
||||||
) -> impl Future<Output = Result<Vec<WeatherAgg>, AWError>> {
|
) -> impl Future<Output = Result<Vec<WeatherAgg>, AWError>> {
|
||||||
let pool = pool.clone();
|
let pool = pool.clone();
|
||||||
web::block(move || match query {
|
web::block(move || {
|
||||||
Queries::GetTopTenHottestYears => get_hottest_years(pool.get()?),
|
// simulate an expensive query, see comments at top of main.rs
|
||||||
Queries::GetTopTenColdestYears => get_coldest_years(pool.get()?),
|
sleep(Duration::from_secs(2));
|
||||||
Queries::GetTopTenHottestMonths => get_hottest_months(pool.get()?),
|
|
||||||
Queries::GetTopTenColdestMonths => get_coldest_months(pool.get()?),
|
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)
|
||||||
})
|
})
|
||||||
.map_err(AWError::from)
|
.map_err(AWError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hottest_years(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
fn get_hottest_years(conn: Connection) -> WeatherAggResult {
|
||||||
let stmt = "
|
let stmt = conn.prepare(
|
||||||
|
"
|
||||||
SELECT cast(strftime('%Y', date) as int) as theyear,
|
SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||||
sum(tmax) as total
|
sum(tmax) as total
|
||||||
FROM nyc_weather
|
FROM nyc_weather
|
||||||
WHERE tmax <> 'TMAX'
|
WHERE tmax <> 'TMAX'
|
||||||
GROUP BY theyear
|
GROUP BY theyear
|
||||||
ORDER BY total DESC LIMIT 10;";
|
ORDER BY total DESC LIMIT 10",
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut prep_stmt = conn.prepare(stmt)?;
|
get_rows_as_annual_agg(stmt)
|
||||||
let annuals = prep_stmt
|
|
||||||
.query_map(NO_PARAMS, |row| WeatherAgg::AnnualAgg {
|
|
||||||
year: row.get(0),
|
|
||||||
total: row.get(1),
|
|
||||||
})
|
|
||||||
.and_then(|mapped_rows| {
|
|
||||||
Ok(mapped_rows
|
|
||||||
.map(|row| row.unwrap())
|
|
||||||
.collect::<Vec<WeatherAgg>>())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
sleep(Duration::from_secs(2)); //see comments at top of main.rs
|
|
||||||
|
|
||||||
Ok(annuals)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_coldest_years(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
fn get_coldest_years(conn: Connection) -> WeatherAggResult {
|
||||||
let stmt = "
|
let stmt = conn.prepare(
|
||||||
|
"
|
||||||
SELECT cast(strftime('%Y', date) as int) as theyear,
|
SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||||
sum(tmax) as total
|
sum(tmax) as total
|
||||||
FROM nyc_weather
|
FROM nyc_weather
|
||||||
WHERE tmax <> 'TMAX'
|
WHERE tmax <> 'TMAX'
|
||||||
GROUP BY theyear
|
GROUP BY theyear
|
||||||
ORDER BY total ASC LIMIT 10;";
|
ORDER BY total ASC LIMIT 10",
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut prep_stmt = conn.prepare(stmt)?;
|
get_rows_as_annual_agg(stmt)
|
||||||
let annuals = prep_stmt
|
|
||||||
.query_map(NO_PARAMS, |row| WeatherAgg::AnnualAgg {
|
|
||||||
year: row.get(0),
|
|
||||||
total: row.get(1),
|
|
||||||
})
|
|
||||||
.and_then(|mapped_rows| {
|
|
||||||
Ok(mapped_rows
|
|
||||||
.map(|row| row.unwrap())
|
|
||||||
.collect::<Vec<WeatherAgg>>())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
sleep(Duration::from_secs(2)); //see comments at top of main.rs
|
|
||||||
|
|
||||||
Ok(annuals)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hottest_months(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
fn get_rows_as_annual_agg(mut statement: Statement) -> WeatherAggResult {
|
||||||
let stmt = "SELECT cast(strftime('%Y', date) as int) as theyear,
|
statement
|
||||||
|
.query_map(NO_PARAMS, |row| {
|
||||||
|
Ok(WeatherAgg::AnnualAgg {
|
||||||
|
year: row.get(0)?,
|
||||||
|
total: row.get(1)?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.and_then(Iterator::collect)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_hottest_months(conn: Connection) -> WeatherAggResult {
|
||||||
|
let stmt = conn.prepare(
|
||||||
|
"SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||||
cast(strftime('%m', date) as int) as themonth,
|
cast(strftime('%m', date) as int) as themonth,
|
||||||
sum(tmax) as total
|
sum(tmax) as total
|
||||||
FROM nyc_weather
|
FROM nyc_weather
|
||||||
WHERE tmax <> 'TMAX'
|
WHERE tmax <> 'TMAX'
|
||||||
GROUP BY theyear, themonth
|
GROUP BY theyear, themonth
|
||||||
ORDER BY total DESC LIMIT 10;";
|
ORDER BY total DESC LIMIT 10",
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut prep_stmt = conn.prepare(stmt)?;
|
get_rows_as_month_agg(stmt)
|
||||||
let annuals = prep_stmt
|
|
||||||
.query_map(NO_PARAMS, |row| WeatherAgg::MonthAgg {
|
|
||||||
year: row.get(0),
|
|
||||||
month: row.get(1),
|
|
||||||
total: row.get(2),
|
|
||||||
})
|
|
||||||
.and_then(|mapped_rows| {
|
|
||||||
Ok(mapped_rows
|
|
||||||
.map(|row| row.unwrap())
|
|
||||||
.collect::<Vec<WeatherAgg>>())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
sleep(Duration::from_secs(2)); //see comments at top of main.rs
|
|
||||||
Ok(annuals)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_coldest_months(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
fn get_coldest_months(conn: Connection) -> WeatherAggResult {
|
||||||
let stmt = "SELECT cast(strftime('%Y', date) as int) as theyear,
|
let stmt = conn.prepare(
|
||||||
|
"SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||||
cast(strftime('%m', date) as int) as themonth,
|
cast(strftime('%m', date) as int) as themonth,
|
||||||
sum(tmax) as total
|
sum(tmax) as total
|
||||||
FROM nyc_weather
|
FROM nyc_weather
|
||||||
WHERE tmax <> 'TMAX'
|
WHERE tmax <> 'TMAX'
|
||||||
GROUP BY theyear, themonth
|
GROUP BY theyear, themonth
|
||||||
ORDER BY total ASC LIMIT 10;";
|
ORDER BY total ASC LIMIT 10",
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut prep_stmt = conn.prepare(stmt)?;
|
get_rows_as_month_agg(stmt)
|
||||||
let annuals = prep_stmt
|
}
|
||||||
.query_map(NO_PARAMS, |row| WeatherAgg::MonthAgg {
|
|
||||||
year: row.get(0),
|
fn get_rows_as_month_agg(mut statement: Statement) -> WeatherAggResult {
|
||||||
month: row.get(1),
|
statement
|
||||||
total: row.get(2),
|
.query_map(NO_PARAMS, |row| {
|
||||||
})
|
Ok(WeatherAgg::MonthAgg {
|
||||||
.and_then(|mapped_rows| {
|
year: row.get(0)?,
|
||||||
Ok(mapped_rows
|
month: row.get(1)?,
|
||||||
.map(|row| row.unwrap())
|
total: row.get(2)?,
|
||||||
.collect::<Vec<WeatherAgg>>())
|
})
|
||||||
})?;
|
})
|
||||||
|
.and_then(Iterator::collect)
|
||||||
sleep(Duration::from_secs(2)); //see comments at top of main.rs
|
|
||||||
Ok(annuals)
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* Actix-Web Asynchronous Database Example
|
/* Actix-Web Asynchronous Database Example
|
||||||
|
|
||||||
This project illustrates two examples:
|
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*,
|
1. An asynchronous handler that executes 4 queries in *sequential order*,
|
||||||
collecting the results and returning them as a single serialized json object
|
collecting the results and returning them as a single serialized json object
|
||||||
|
@ -13,5 +13,5 @@ env_logger = "0.6"
|
|||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
|
||||||
r2d2 = "0.8"
|
r2d2 = "0.8"
|
||||||
r2d2_sqlite = "0.8"
|
r2d2_sqlite = "0.10"
|
||||||
rusqlite = "0.16"
|
rusqlite = "0.18"
|
||||||
|
BIN
r2d2/test.db
BIN
r2d2/test.db
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user