Переписал на pool

This commit is contained in:
Кобелев Андрей Андреевич 2022-10-13 12:01:56 +03:00
parent 6fb20ef6d7
commit 3360706756
5 changed files with 113 additions and 62 deletions

32
Cargo.lock generated
View File

@ -1244,6 +1244,8 @@ dependencies = [
"deadpool-postgres", "deadpool-postgres",
"env_logger", "env_logger",
"log", "log",
"r2d2",
"r2d2_sqlite",
"rusqlite", "rusqlite",
"serde", "serde",
"sqlx", "sqlx",
@ -1644,6 +1646,27 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "r2d2"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
dependencies = [
"log",
"parking_lot 0.12.1",
"scheduled-thread-pool",
]
[[package]]
name = "r2d2_sqlite"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f5d0337e99cd5cacd91ffc326c6cc9d8078def459df560c4f9bf9ba4a51034"
dependencies = [
"r2d2",
"rusqlite",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -1786,6 +1809,15 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "scheduled-thread-pool"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf"
dependencies = [
"parking_lot 0.12.1",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"

View File

@ -13,6 +13,8 @@ serde = "1.0.8"
deadpool-postgres = { version = "0.10.2", features = ["serde"] } deadpool-postgres = { version = "0.10.2", features = ["serde"] }
tokio-postgres = "0.7.6" tokio-postgres = "0.7.6"
rusqlite = { version = "0.28.0", features = ["bundled"] } rusqlite = { version = "0.28.0", features = ["bundled"] }
r2d2 = "0.8"
r2d2_sqlite = "0.21"
actix-files = "0.6" actix-files = "0.6"
env_logger = "0.9.0" env_logger = "0.9.0"
log = "0.4" log = "0.4"

View File

@ -1,8 +1,7 @@
use rusqlite::{Connection, Error, Result}; use rusqlite::{Error, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Cat { pub struct Cat {
id: i32, id: i32,
@ -20,22 +19,26 @@ pub type CatsResult = Result<Vec<Cat>, Error>;
pub type ColorsResult = Result<Vec<Color>, Error>; pub type ColorsResult = Result<Vec<Color>, Error>;
pub type CatResult = Result<Cat, Error>; pub type CatResult = Result<Cat, Error>;
pub type ColorResult = Result<Color, Error>; pub type ColorResult = Result<Color, Error>;
pub type Pool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
// Сервис базы данных // Сервис базы данных
#[derive(std::clone::Clone)]
pub struct Service { pub struct Db {
db: rusqlite::Connection, pool: Pool,
} }
impl Service {
impl Db {
pub async fn new(pool: Pool) -> Db {
return Db { pool: pool };
}
// Создание сервиса // Создание сервиса
pub fn new() -> Service { pub async fn init(&self) {
let conn = Connection::open("cats.db"); let conn = match self.pool.get() {
let db_con = match conn {
Ok(conn) => conn, Ok(conn) => conn,
Err(error) => panic!("Problem opening the db: {:?}", error), Err(err) => panic!("{}", err),
}; };
db_con
.execute( conn.execute(
"create table if not exists cat_colors ( "create table if not exists cat_colors (
id integer primary key, id integer primary key,
name text not null unique name text not null unique
@ -43,8 +46,7 @@ impl Service {
[], [],
) )
.ok(); .ok();
db_con conn.execute(
.execute(
"create table if not exists cats ( "create table if not exists cats (
id integer primary key, id integer primary key,
name text not null, name text not null,
@ -57,27 +59,29 @@ impl Service {
cat_colors.insert(String::from("Blue"), vec!["Tigger", "Sammy"]); cat_colors.insert(String::from("Blue"), vec!["Tigger", "Sammy"]);
cat_colors.insert(String::from("Black"), vec!["Oreo", "Biscuit"]); cat_colors.insert(String::from("Black"), vec!["Oreo", "Biscuit"]);
for (color, catnames) in &cat_colors { for (color, catnames) in &cat_colors {
db_con conn.execute(
.execute(
"INSERT INTO cat_colors (name) values (?1)", "INSERT INTO cat_colors (name) values (?1)",
&[&color.to_string()], &[&color.to_string()],
) )
.ok(); .ok();
let last_id: String = db_con.last_insert_rowid().to_string(); let last_id: String = conn.last_insert_rowid().to_string();
for cat in catnames { for cat in catnames {
db_con conn.execute(
.execute(
"INSERT INTO cats (name, color_id) values (?1, ?2)", "INSERT INTO cats (name, color_id) values (?1, ?2)",
&[&cat.to_string(), &last_id], &[&cat.to_string(), &last_id],
) )
.ok(); .ok();
} }
} }
return Service { db: db_con };
} }
// Получение кошек // Получение кошек
pub fn get_cats(&self) -> CatsResult { pub fn get_cats(&self) -> CatsResult {
let mut stmt = self.db.prepare( let conn = match self.pool.get() {
Ok(conn) => conn,
Err(err) => panic!("{}", err),
};
let mut stmt = conn.prepare(
"SELECT c.id, c.name, cc.name from cats c INNER JOIN cat_colors cc ON cc.id = c.color_id;", "SELECT c.id, c.name, cc.name from cats c INNER JOIN cat_colors cc ON cc.id = c.color_id;",
)?; )?;
return stmt return stmt
@ -93,7 +97,11 @@ impl Service {
// Получение цветов // Получение цветов
pub fn get_colors(&self) -> ColorsResult { pub fn get_colors(&self) -> ColorsResult {
let mut stmt = self.db.prepare("SELECT id, name from cat_colors")?; let conn = match self.pool.get() {
Ok(conn) => conn,
Err(err) => panic!("{}", err),
};
let mut stmt = conn.prepare("SELECT id, name from cat_colors")?;
return stmt return stmt
.query_map([], |row| { .query_map([], |row| {
Ok(Color { Ok(Color {
@ -106,7 +114,11 @@ impl Service {
// Добавление кошки // Добавление кошки
pub fn add_cat(&self, cat_name: String, cat_color: String) -> CatResult { pub fn add_cat(&self, cat_name: String, cat_color: String) -> CatResult {
return self.db.query_row("INSERT INTO cats (name, color_id) SELECT ?1, id FROM cat_colors cc WHERE name = ?2 RETURNING id, name, ?2", let conn = match self.pool.get() {
Ok(conn) => conn,
Err(err) => panic!("{}", err),
};
return conn.query_row("INSERT INTO cats (name, color_id) SELECT ?1, id FROM cat_colors cc WHERE name = ?2 RETURNING id, name, ?2",
[cat_name, cat_color], [cat_name, cat_color],
|row| { |row| {
Ok(Cat { Ok(Cat {
@ -119,7 +131,11 @@ impl Service {
} }
// Добавление цвета // Добавление цвета
pub fn add_color(&self, color_name: String) -> ColorResult { pub fn add_color(&self, color_name: String) -> ColorResult {
return self.db.query_row( let conn = match self.pool.get() {
Ok(conn) => conn,
Err(err) => panic!("{}", err),
};
return conn.query_row(
"INSERT INTO cat_colors (name) VALUES (?1) RETURNING id, name", "INSERT INTO cat_colors (name) VALUES (?1) RETURNING id, name",
[color_name], [color_name],
|row| { |row| {

View File

@ -1,35 +1,32 @@
pub mod db; pub mod db;
use actix_web::{get,post, web, HttpResponse, Responder, Result}; use db::{Db};
use actix_web::{get, post, web, HttpResponse, Responder, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub struct Service {
pub db: db::Service,
}
#[derive(Serialize)] #[derive(Serialize)]
struct ArrayResponse<T> { struct ArrayResponse<T> {
result: Vec<T>, result: Vec<T>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct AddColorRequest { pub struct AddColorRequest {
pub name: String, pub name: String,
} }
#[get("/cats")] #[get("/cats")]
pub async fn get_cats(ctx: web::Data<Service>) -> Result<impl Responder> { pub async fn get_cats(db: web::Data<Db>) -> Result<impl Responder> {
let cats = ctx.db.get_cats();
let cats = db.get_cats();
let res = match cats { let res = match cats {
Ok(v) => ArrayResponse{ result: v }, Ok(v) => ArrayResponse { result: v },
Err(_err) => ArrayResponse { result: vec![] }, Err(_err) => ArrayResponse { result: vec![] },
}; };
return Ok(HttpResponse::Ok().json(res)); return Ok(HttpResponse::Ok().json(res));
} }
#[get("/colors")] #[get("/colors")]
pub async fn get_colors(ctx: web::Data<Service>) -> Result<impl Responder> { pub async fn get_colors(db: web::Data<Db>) -> Result<impl Responder> {
let colors = ctx.db.get_colors(); let colors = db.get_colors();
let res = match colors { let res = match colors {
Ok(v) => ArrayResponse { result: v }, Ok(v) => ArrayResponse { result: v },
Err(_err) => ArrayResponse { result: vec![] }, Err(_err) => ArrayResponse { result: vec![] },
@ -43,14 +40,13 @@ pub struct AddCatRequest {
pub color: String, pub color: String,
} }
#[post("/add/cat")] #[post("/add/cat")]
pub async fn add_cat( pub async fn add_cat(
ctx: web::Data<Service>, db: web::Data<Db>,
cat: web::Json<AddCatRequest>, cat: web::Json<AddCatRequest>,
) -> Result<impl Responder> { ) -> Result<impl Responder> {
let _cat = cat.into_inner(); let _cat = cat.into_inner();
let cat = ctx.db.add_cat(_cat.name, _cat.color); let cat = db.add_cat(_cat.name, _cat.color);
let res = match cat { let res = match cat {
Ok(v) => ArrayResponse { result: vec![v] }, Ok(v) => ArrayResponse { result: vec![v] },
Err(_err) => panic!("{:?}", _err), Err(_err) => panic!("{:?}", _err),
@ -60,15 +56,14 @@ pub async fn add_cat(
#[post("/add/color")] #[post("/add/color")]
pub async fn add_color( pub async fn add_color(
ctx: web::Data<Service>, db: web::Data<Db>,
cat: web::Json<AddColorRequest>, cat: web::Json<AddColorRequest>,
) -> Result<impl Responder> { ) -> Result<impl Responder> {
let _color = cat.into_inner(); let _color = cat.into_inner();
let cat = ctx.db.add_color(_color.name); let cat = db.add_color(_color.name);
let res = match cat { let res = match cat {
Ok(v) => ArrayResponse { result: vec![v] }, Ok(v) => ArrayResponse { result: vec![v] },
Err(_err) => panic!("{:?}", _err), Err(_err) => panic!("{:?}", _err),
}; };
return Ok(HttpResponse::Ok().json(res)); return Ok(HttpResponse::Ok().json(res));
} }

View File

@ -1,8 +1,10 @@
use config::Config; use config::Config;
mod cfg;
mod cats; mod cats;
mod cfg;
use actix_files::Files; use actix_files::Files;
use actix_web::{web, App, HttpServer}; use actix_web::{middleware, web, App, HttpServer};
use cats::db::{Db, Pool};
use r2d2_sqlite::{self, SqliteConnectionManager};
#[actix_web::main] #[actix_web::main]
pub async fn main() -> std::io::Result<()> { pub async fn main() -> std::io::Result<()> {
@ -18,11 +20,15 @@ pub async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
log::info!("starting HTTP server at http://{}:{}", app.host, app.port); log::info!("starting HTTP server at http://{}:{}", app.host, app.port);
HttpServer::new(|| { let manager = SqliteConnectionManager::file("cats.db");
let pool = Pool::new(manager).unwrap();
let db = Db::new(pool.clone()).await;
db.init().await;
HttpServer::new(move || {
App::new() App::new()
.app_data(web::Data::new(cats::Service { .app_data(web::Data::new(db.clone()))
db: cats::db::Service::new(), .wrap(middleware::Logger::default())
}))
.service(cats::get_cats) .service(cats::get_cats)
.service(cats::get_colors) .service(cats::get_colors)
.service(cats::add_cat) .service(cats::add_cat)